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/screen/data_network_service/data_network_service_viewmodel.dart
View file @
0bf528a4
...
@@ -3,13 +3,14 @@ import 'package:get/get_rx/src/rx_types/rx_types.dart';
...
@@ -3,13 +3,14 @@ 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/data_network_service/product_network_data_model.dart'
;
import
'package:mypoint_flutter_app/screen/data_network_service/product_network_data_model.dart'
;
import
'package:mypoint_flutter_app/widgets/custom_toast_message.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/contact_storage_service.dart'
;
import
'../../preference/contact_storage_service.dart'
;
import
'../../preference/point/point_manager.dart'
;
import
'../../preference/point/point_manager.dart'
;
import
'../topup/models/brand_network_model.dart'
;
import
'../voucher/models/product_brand_model.dart'
;
import
'../voucher/models/product_brand_model.dart'
;
import
'../voucher/models/product_model.dart'
;
import
'../voucher/models/product_type.dart'
;
class
DataNetworkServiceViewModel
extends
RestfulApiViewModel
{
class
DataNetworkServiceViewModel
extends
RestfulApiViewModel
{
final
RxList
<
String
>
histories
=
<
String
>[].
obs
;
final
RxList
<
String
>
histories
=
<
String
>[].
obs
;
...
@@ -17,9 +18,9 @@ class DataNetworkServiceViewModel extends RestfulApiViewModel {
...
@@ -17,9 +18,9 @@ class DataNetworkServiceViewModel extends RestfulApiViewModel {
final
RxList
<
TopUpNetworkDataModel
>
topUpNetworkData
=
<
TopUpNetworkDataModel
>[].
obs
;
final
RxList
<
TopUpNetworkDataModel
>
topUpNetworkData
=
<
TopUpNetworkDataModel
>[].
obs
;
final
Map
<
String
,
List
<
TopUpNetworkDataModel
>>
_allValue
=
{};
final
Map
<
String
,
List
<
TopUpNetworkDataModel
>>
_allValue
=
{};
var
selectedBrand
=
Rxn
<
ProductBrandModel
>();
final
Rxn
<
ProductBrandModel
>
selectedBrand
=
Rxn
<
ProductBrandModel
>();
var
selectedProduct
=
Rxn
<
ProductNetworkDataModel
>();
final
Rxn
<
ProductNetworkDataModel
>
selectedProduct
=
Rxn
<
ProductNetworkDataModel
>();
var
phoneNumber
=
''
.
obs
;
final
RxString
phoneNumber
=
''
.
obs
;
void
Function
(
String
message
)?
onShowAlertError
;
void
Function
(
String
message
)?
onShowAlertError
;
void
Function
(
String
message
)?
onShowAlertRedeemSuccess
;
void
Function
(
String
message
)?
onShowAlertRedeemSuccess
;
...
@@ -48,43 +49,44 @@ class DataNetworkServiceViewModel extends RestfulApiViewModel {
...
@@ -48,43 +49,44 @@ class DataNetworkServiceViewModel extends RestfulApiViewModel {
}
}
}
}
firstLoadNetworkData
()
async
{
Future
<
void
>
firstLoadNetworkData
()
async
{
_getNetworkBrands
();
await
_getNetworkBrands
();
}
}
_getNetworkBrands
()
{
Future
<
void
>
_getNetworkBrands
()
async
{
showLoading
();
await
callApi
<
List
<
ProductBrandModel
>>(
client
.
productTopUpBrands
().
then
((
response
)
{
request:
()
=>
client
.
productTopUpBrands
(),
topUpBrands
.
assignAll
(
response
.
data
??
[]);
onSuccess:
(
data
,
_
)
{
hideLoading
();
topUpBrands
.
assignAll
(
data
);
checkMobileNetwork
();
checkMobileNetwork
();
}).
catchError
((
error
)
{
},
hideLoading
();
onFailure:
(
mgs
,
_
,
_
)
async
{
print
(
'Error fetching brands topup:
$error
'
);
topUpBrands
.
clear
();
});
onShowAlertError
?.
call
(
mgs
);
},
);
}
}
checkMobileNetwork
()
{
Future
<
void
>
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
??
''
;
?
topUpBrands
.
firstWhere
(
var
brand
=
topUpBrands
.
isNotEmpty
(
brand
)
=>
brand
.
code
==
brandCode
,
?
topUpBrands
.
firstWhere
(
orElse:
()
=>
topUpBrands
.
first
,
(
b
)
=>
b
.
code
==
brandCode
,
)
:
null
;
orElse:
()
=>
topUpBrands
.
first
,
selectedBrand
.
value
=
brand
;
)
hideLoading
();
:
topUpBrands
.
firstOrNull
;
getTelcoDetail
();
selectedBrand
.
value
=
brand
;
}).
catchError
((
error
)
{
getTelcoDetail
();
final
first
=
topUpBrands
.
firstOrNull
;
},
if
(
first
!=
null
)
{
onFailure:
(
_
,
_
,
_
)
async
{
selectedBrand
.
value
=
first
;
final
first
=
topUpBrands
.
firstOrNull
;
}
if
(
first
!=
null
)
selectedBrand
.
value
=
first
;
hideLoading
();
getTelcoDetail
();
getTelcoDetail
();
},
print
(
'Error checking mobile network:
$error
'
);
);
});
}
}
Future
<
void
>
getTelcoDetail
({
String
?
selected
})
async
{
Future
<
void
>
getTelcoDetail
({
String
?
selected
})
async
{
...
@@ -94,12 +96,10 @@ class DataNetworkServiceViewModel extends RestfulApiViewModel {
...
@@ -94,12 +96,10 @@ class DataNetworkServiceViewModel extends RestfulApiViewModel {
void
makeSelected
(
List
<
TopUpNetworkDataModel
>
data
)
{
void
makeSelected
(
List
<
TopUpNetworkDataModel
>
data
)
{
bool
didSelect
=
false
;
bool
didSelect
=
false
;
final
list
=
data
final
list
=
data
.
expand
((
e
)
=>
e
.
products
??
[]).
toList
();
.
expand
((
e
)
=>
e
.
products
??
[])
.
toList
();
if
(
selected
!=
null
&&
selected
.
isNotEmpty
)
{
if
(
selected
!=
null
&&
selected
.
isNotEmpty
)
{
for
(
var
item
in
list
)
{
for
(
var
item
in
list
)
{
final
isMatch
=
item
==
int
.
tryParse
(
selected
);
final
isMatch
=
item
.
id
==
int
.
tryParse
(
selected
);
if
(
isMatch
)
{
if
(
isMatch
)
{
selectedProduct
.
value
=
item
;
selectedProduct
.
value
=
item
;
didSelect
=
true
;
didSelect
=
true
;
...
@@ -117,43 +117,34 @@ class DataNetworkServiceViewModel extends RestfulApiViewModel {
...
@@ -117,43 +117,34 @@ class DataNetworkServiceViewModel extends RestfulApiViewModel {
makeSelected
(
cached
);
makeSelected
(
cached
);
return
;
return
;
}
}
showLoading
();
await
callApi
<
List
<
TopUpNetworkDataModel
>>(
try
{
request:
()
=>
client
.
getNetworkProducts
((
id
??
0
).
toString
()),
final
result
=
await
client
.
getNetworkProducts
((
id
??
0
).
toString
());
onSuccess:
(
data
,
_
)
{
var
data
=
result
.
data
??
[];
final
filtered
=
(
data
)
data
=
data
.
where
((
e
)
=>
e
.
products
?.
isNotEmpty
==
true
)
.
where
((
e
)
=>
e
.
products
?.
isNotEmpty
==
true
)
.
toList
();
.
toList
();
_allValue
[
code
??
""
]
=
filtered
;
_allValue
[
code
??
""
]
=
data
;
topUpNetworkData
.
assignAll
(
filtered
);
topUpNetworkData
.
assignAll
(
data
);
makeSelected
(
filtered
);
makeSelected
(
data
);
},
hideLoading
();
onFailure:
(
_
,
_
,
_
)
async
{},
}
catch
(
error
)
{
);
print
(
"Error fetching all products:
$error
"
);
hideLoading
();
}
}
}
redeemProductMobileCard
()
async
{
Future
<
void
>
redeemProductMobileCard
()
async
{
final
id
=
selectedProduct
.
value
?.
id
;
final
id
=
selectedProduct
.
value
?.
id
;
if
(
id
==
null
)
{
if
(
id
==
null
)
{
onShowAlertError
?.
call
(
"Vui lòng chọn sản phẩm"
);
showToastMessage
(
'Vui lòng chọn sản phẩm'
);
return
;
}
showLoading
();
try
{
final
response
=
await
client
.
redeemProductTopUps
(
id
,
phoneNumber
.
value
);
hideLoading
();
if
(!
response
.
isSuccess
)
{
onShowAlertError
?.
call
(
response
.
errorMessage
??
Constants
.
commonError
);
return
;
}
final
mgs
=
(
response
.
errorMessage
??
""
).
isEmpty
?
"Chúc mừng bạn đã đổi Ưu đãi data thành công"
:
(
response
.
errorMessage
??
""
);
onShowAlertRedeemSuccess
?.
call
(
mgs
);
}
catch
(
error
)
{
hideLoading
();
onShowAlertError
?.
call
(
error
.
toString
());
return
;
return
;
}
}
await
callApi
<
EmptyCodable
>(
request:
()
=>
client
.
redeemProductTopUps
(
id
,
phoneNumber
.
value
),
onSuccess:
(
data
,
_
)
{
onShowAlertRedeemSuccess
?.
call
(
"Chúc mừng bạn đã đổi Ưu đãi data thành công"
);
},
onFailure:
(
msg
,
_
,
_
)
async
{
onShowAlertError
?.
call
(
msg
.
isNotEmpty
?
msg
:
Constants
.
commonError
);
},
);
}
}
}
}
\ No newline at end of file
lib/screen/delete_account/delete_account_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
'package:mypoint_flutter_app/preference/data_preference.dart'
;
import
'package:mypoint_flutter_app/preference/data_preference.dart'
;
import
'package:mypoint_flutter_app/widgets/custom_toast_message.dart'
;
import
'../../networking/restful_api_viewmodel.dart'
;
import
'../../networking/restful_api_viewmodel.dart'
;
import
'../../configs/constants.dart'
;
import
'../../configs/constants.dart'
;
import
'../otp/delete_account_otp_repository.dart'
;
import
'../otp/delete_account_otp_repository.dart'
;
import
'../otp/model/create_otp_response_model.dart'
;
import
'../otp/otp_screen.dart'
;
import
'../otp/otp_screen.dart'
;
import
'../otp/verify_otp_repository.dart'
;
class
DeleteAccountViewModel
extends
RestfulApiViewModel
{
class
DeleteAccountViewModel
extends
RestfulApiViewModel
{
RxBool
agreed
=
false
.
obs
;
final
RxBool
agreed
=
false
.
obs
;
void
confirmDelete
()
{
Future
<
void
>
confirmDelete
()
async
{
if
(
agreed
.
value
)
{
if
(!
agreed
.
value
)
{
showLoading
();
showToastMessage
(
"Bạn cần đồng ý với điều khoản để tiếp tục."
);
client
.
requestOtpDeleteAccount
().
then
((
value
)
{
return
;
hideLoading
();
if
(
value
.
isSuccess
)
{
final
phone
=
DataPreference
.
instance
.
phone
??
""
;
Get
.
to
(
()
=>
OtpScreen
(
repository:
DeleteAccountOtpRepository
(
phone
,
value
.
data
?.
resendAfterSecond
??
Constants
.
otpTtl
)),
);
}
else
{
final
mgs
=
value
.
errorMessage
??
Constants
.
commonError
;
Get
.
snackbar
(
"Thông báo"
,
mgs
);
}
});
}
else
{
Get
.
snackbar
(
"Thông báo"
,
"Bạn cần đồng ý với điều khoản để tiếp tục."
);
}
}
await
callApi
<
CreateOTPResponseModel
>(
request:
()
=>
client
.
requestOtpDeleteAccount
(),
onSuccess:
(
data
,
_
)
{
final
phone
=
DataPreference
.
instance
.
phone
??
""
;
final
ttl
=
data
.
resendAfterSecond
??
Constants
.
otpTtl
;
Get
.
to
(()
=>
OtpScreen
(
repository:
DeleteAccountOtpRepository
(
phone
,
ttl
)));
},
onFailure:
(
msg
,
_
,
_
)
async
{
showToastMessage
(
msg
);
},
);
}
}
}
}
lib/screen/device_manager/device_manager_viewmodel.dart
View file @
0bf528a4
...
@@ -5,54 +5,51 @@ import '../../networking/restful_api_viewmodel.dart';
...
@@ -5,54 +5,51 @@ import '../../networking/restful_api_viewmodel.dart';
import
'device_manager_model.dart'
;
import
'device_manager_model.dart'
;
class
DeviceManagerViewModel
extends
RestfulApiViewModel
{
class
DeviceManagerViewModel
extends
RestfulApiViewModel
{
var
logoutDevicesResponse
=
Rxn
<
DevicesLogoutListResponse
>();
final
Rxn
<
DevicesLogoutListResponse
>
logoutDevicesResponse
=
Rxn
<
DevicesLogoutListResponse
>();
var
currentDevice
=
Rxn
<
DeviceItemModel
>();
final
Rxn
<
DeviceItemModel
>
currentDevice
=
Rxn
<
DeviceItemModel
>();
void
Function
(
String
message
)?
onShowAlertError
;
void
Function
(
String
message
)?
onShowAlertError
;
getData
()
{
void
getData
()
{
getLogoutDevicesResponse
();
getLogoutDevicesResponse
();
getCurrentDevice
();
getCurrentDevice
();
}
}
Future
<
void
>
getLogoutDevicesResponse
()
async
{
Future
<
void
>
getLogoutDevicesResponse
()
async
{
final
body
=
{
"page"
:
0
,
"limit"
:
200
};
final
body
=
{
"page"
:
0
,
"limit"
:
200
};
showLoading
();
await
callApi
<
DevicesLogoutListResponse
>(
try
{
request:
()
=>
client
.
getLogoutDevices
(
body
),
final
response
=
await
client
.
getLogoutDevices
(
body
);
onSuccess:
(
data
,
_
)
{
hideLoading
();
logoutDevicesResponse
.
value
=
data
;
if
(
response
.
isSuccess
&&
response
.
data
!=
null
)
{
},
logoutDevicesResponse
.
value
=
response
.
data
;
onFailure:
(
msg
,
_
,
_
)
async
{
}
else
{
onShowAlertError
?.
call
(
msg
);
onShowAlertError
?.
call
(
response
.
message
??
Constants
.
commonError
);
},
}
);
}
catch
(
error
)
{
hideLoading
();
onShowAlertError
?.
call
(
Constants
.
commonError
);
}
}
}
Future
<
void
>
getCurrentDevice
()
async
{
Future
<
void
>
getCurrentDevice
()
async
{
final
response
=
await
client
.
getCurrentDevice
();
await
callApi
<
DeviceItemModel
>(
if
(
response
.
isSuccess
&&
response
.
data
!=
null
)
{
request:
()
=>
client
.
getCurrentDevice
(),
currentDevice
.
value
=
response
.
data
;
onSuccess:
(
data
,
_
)
{
}
currentDevice
.
value
=
data
;
},
onFailure:
(
_
,
_
,
_
)
async
{},
withLoading:
false
,
);
}
}
Future
<
void
>
deleteDevice
(
DeviceItemModel
item
)
async
{
Future
<
void
>
deleteDevice
(
DeviceItemModel
item
)
async
{
if
((
item
.
deviceKey
??
''
).
isEmpty
)
return
;
final
key
=
item
.
deviceKey
??
''
;
showLoading
();
if
(
key
.
isEmpty
)
return
;
try
{
await
callApi
<
String
>(
final
response
=
await
client
.
deleteDevice
(
item
.
deviceKey
??
''
);
request:
()
=>
client
.
deleteDevice
(
key
),
hideLoading
();
onSuccess:
(
data
,
_
)
async
{
if
(
response
.
isSuccess
)
{
await
getLogoutDevicesResponse
();
getLogoutDevicesResponse
();
onShowAlertError
?.
call
(
data
);
onShowAlertError
?.
call
(
response
.
data
??
"Đã xóa thiết bị thành công"
);
},
}
else
{
onFailure:
(
msg
,
_
,
_
)
async
{
onShowAlertError
?.
call
(
response
.
message
??
Constants
.
commonError
);
onShowAlertError
?.
call
(
msg
);
}
},
}
catch
(
error
)
{
);
hideLoading
();
onShowAlertError
?.
call
(
"Error fetching product detail:
$error
"
);
}
}
}
}
}
lib/screen/electric_payment/electric_payment_bill_screen.dart
View file @
0bf528a4
import
'package:flutter/material.dart'
;
import
'package:flutter/material.dart'
;
import
'package:get/get.dart'
;
import
'package:get/get.dart'
;
import
'package:get/get_core/src/get_main.dart'
;
import
'package:get/get_state_manager/src/rx_flutter/rx_obx_widget.dart'
;
import
'package:mypoint_flutter_app/extensions/num_extension.dart'
;
import
'package:mypoint_flutter_app/extensions/num_extension.dart'
;
import
'package:mypoint_flutter_app/widgets/image_loader.dart'
;
import
'package:mypoint_flutter_app/widgets/image_loader.dart'
;
import
'../../resources/base_color.dart'
;
import
'../../resources/base_color.dart'
;
...
...
lib/screen/electric_payment/electric_payment_bill_viewmodel.dart
View file @
0bf528a4
...
@@ -2,48 +2,43 @@ import 'package:get/get_rx/src/rx_types/rx_types.dart';
...
@@ -2,48 +2,43 @@ import 'package:get/get_rx/src/rx_types/rx_types.dart';
import
'package:mypoint_flutter_app/extensions/collection_extension.dart'
;
import
'package:mypoint_flutter_app/extensions/collection_extension.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
'../../configs/constants.dart'
;
import
'../transaction/model/payment_method_model.dart'
;
import
'../transaction/model/payment_method_model.dart'
;
import
'models/customer_contract_object_model.dart'
;
import
'models/customer_contract_object_model.dart'
;
import
'models/electric_payment_response_model.dart'
;
import
'models/electric_payment_response_model.dart'
;
class
ElectricPaymentBillViewModel
extends
RestfulApiViewModel
{
class
ElectricPaymentBillViewModel
extends
RestfulApiViewModel
{
var
paymentMethods
=
RxList
<
PaymentMethodModel
>
()
;
final
RxList
<
PaymentMethodModel
>
paymentMethods
=
<
PaymentMethodModel
>
[].
obs
;
var
selectedPaymentMethodIndex
=
0
.
obs
;
final
RxInt
selectedPaymentMethodIndex
=
0
.
obs
;
void
Function
(
ElectricPaymentResponseModel
data
)?
customerEvnPaymentGatewayResponse
;
void
Function
(
ElectricPaymentResponseModel
data
)?
customerEvnPaymentGatewayResponse
;
void
Function
(
String
message
)?
onShowAlertError
;
void
Function
(
String
message
)?
onShowAlertError
;
Future
<
void
>
getPaymentMethods
()
async
{
Future
<
void
>
getPaymentMethods
()
async
{
showLoading
();
await
callApi
<
List
<
PaymentMethodModel
>>(
try
{
request:
()
=>
client
.
getPreviewPaymentMethods
(),
final
response
=
await
client
.
getPreviewPaymentMethods
();
onSuccess:
(
data
,
_
)
{
hideLoading
();
selectedPaymentMethodIndex
.
value
=
0
;
selectedPaymentMethodIndex
.
value
=
0
;
paymentMethods
.
assignAll
(
data
);
paymentMethods
.
value
=
response
.
data
??
[];
},
}
catch
(
error
)
{
onFailure:
(
_
,
_
,
_
)
async
{},
hideLoading
();
);
}
}
}
customerEvnPaymentGatewayRequest
(
CustomerContractModel
bill
)
async
{
Future
<
void
>
customerEvnPaymentGatewayRequest
(
CustomerContractModel
bill
)
async
{
final
paymentMethod
=
paymentMethods
.
value
.
safe
(
selectedPaymentMethodIndex
.
value
??
0
)
??
paymentMethods
.
firstOrNull
;
final
paymentMethod
=
paymentMethods
.
safe
(
selectedPaymentMethodIndex
.
value
)
??
paymentMethods
.
firstOrNull
;
final
paymentMethodType
=
paymentMethod
?.
type
?.
methodBillEVN
??
''
;
final
paymentMethodType
=
paymentMethod
?.
type
?.
methodBillEVN
??
''
;
if
(
paymentMethodType
.
isEmpty
)
{
if
(
paymentMethodType
.
isEmpty
)
{
onShowAlertError
?.
call
(
"Vui lòng chọn phương thức thanh toán."
);
onShowAlertError
?.
call
(
"Vui lòng chọn phương thức thanh toán."
);
return
;
return
;
}
}
showLoading
();
await
callApi
<
ElectricPaymentResponseModel
>(
try
{
request:
()
=>
client
.
customerEvnPaymentGatewayRequest
(
bill
,
paymentMethodType
),
final
response
=
await
client
.
customerEvnPaymentGatewayRequest
(
bill
,
paymentMethodType
);
onSuccess:
(
data
,
_
)
{
hideLoading
();
customerEvnPaymentGatewayResponse
?.
call
(
data
);
if
(
response
.
isSuccess
&&
response
.
data
!=
null
)
{
},
customerEvnPaymentGatewayResponse
?.
call
(
response
.
data
!);
onFailure:
(
msg
,
_
,
_
)
async
{
}
else
{
onShowAlertError
?.
call
(
msg
);
onShowAlertError
?.
call
(
response
.
errorMessage
??
"Lỗi khi thanh toán, vui lòng thử lại sau."
);
},
}
defaultError:
"Lỗi khi thanh toán, vui lòng thử lại sau."
,
}
catch
(
error
)
{
);
hideLoading
();
onShowAlertError
?.
call
(
Constants
.
commonError
);
}
}
}
}
}
lib/screen/electric_payment/electric_payment_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
'../../networking/restful_api_viewmodel.dart'
;
import
'../../networking/restful_api_viewmodel.dart'
;
import
'../../configs/constants.dart'
;
import
'electric_payment_bill_screen.dart'
;
import
'electric_payment_bill_screen.dart'
;
import
'models/customer_contract_object_model.dart'
;
import
'models/customer_contract_object_model.dart'
;
...
@@ -10,47 +9,44 @@ class ElectricPaymentViewModel extends RestfulApiViewModel {
...
@@ -10,47 +9,44 @@ class ElectricPaymentViewModel extends RestfulApiViewModel {
final
RxList
<
CustomerContractModel
>
billContracts
=
<
CustomerContractModel
>[].
obs
;
final
RxList
<
CustomerContractModel
>
billContracts
=
<
CustomerContractModel
>[].
obs
;
void
customerContractRequestSearch
(
String
maKH
)
{
void
customerContractRequestSearch
(
String
maKH
)
{
showLoading
();
callApi
<
CustomerContractModel
>(
client
.
customerContractRequestSearch
(
maKH
).
then
((
value
)
{
request:
()
=>
client
.
customerContractRequestSearch
(
maKH
),
hideLoading
();
onSuccess:
(
data
,
_
)
{
final
result
=
value
.
data
;
if
((
data
.
amount
??
0
)
==
0
)
{
if
(!
value
.
isSuccess
)
{
onShowAlertError
?.
call
(
value
.
errorMessage
??
"Không tìm thấy thông tin mã khách hàng, vui lòng kiểm tra và thử lại."
,
);
}
else
if
(
result
!=
null
)
{
if
((
result
.
amount
??
0
)
==
0
)
{
onShowAlertError
?.
call
(
"Bạn đã thanh toán hết hóa đơn."
);
onShowAlertError
?.
call
(
"Bạn đã thanh toán hết hóa đơn."
);
}
else
{
}
else
{
Get
.
to
(
ElectricPaymentBillScreen
(
bill:
result
,
));
Get
.
to
(
ElectricPaymentBillScreen
(
bill:
data
));
}
}
}
else
{
},
onShowAlertError
?.
call
(
"Không tìm thấy thông tin mã khách hàng, vui lòng kiểm tra và thử lại."
);
onFailure:
(
msg
,
_
,
_
)
async
{
}
onShowAlertError
?.
call
(
msg
);
});
},
defaultError:
"Không tìm thấy thông tin mã khách hàng, vui lòng kiểm tra và thử lại."
);
}
}
void
customerContractSearchHistoryGetList
()
{
void
customerContractSearchHistoryGetList
()
{
showLoading
();
callApi
<
List
<
CustomerContractModel
>>(
client
.
customerContractSearchHistoryGetList
()
.
then
((
value
)
{
request:
()
=>
client
.
customerContractSearchHistoryGetList
()
,
hideLoading
();
onSuccess:
(
data
,
_
)
{
final
result
=
value
.
data
;
billContracts
.
assignAll
(
data
)
;
if
(!
value
.
isSuccess
&&
result
==
null
)
{
},
onShowAlertError
?.
call
(
value
.
errorMessage
??
Constants
.
commonError
);
onFailure:
(
msg
,
_
,
_
)
async
{
}
else
{
billContracts
.
clear
();
billContracts
.
value
=
result
??
[]
;
onShowAlertError
?.
call
(
msg
)
;
}
}
,
}
);
);
}
}
void
customerContractDelete
(
String
code
)
{
void
customerContractDelete
(
String
code
)
{
showLoading
();
callApi
<
bool
>(
client
.
customerContractDelete
(
code
).
then
((
value
)
{
request:
()
=>
client
.
customerContractDelete
(
code
),
hideLoading
();
onSuccess:
(
_
,
_
)
{
if
(!
value
.
isSuccess
)
{
customerContractSearchHistoryGetList
();
onShowAlertError
?.
call
(
value
.
errorMessage
??
Constants
.
commonError
,);
},
}
onFailure:
(
msg
,
_
,
_
)
async
{
customerContractSearchHistoryGetList
();
onShowAlertError
?.
call
(
msg
);
});
},
);
}
}
}
}
lib/screen/faqs/faqs_screen.dart
View file @
0bf528a4
...
@@ -3,8 +3,10 @@ import 'package:flutter/material.dart';
...
@@ -3,8 +3,10 @@ import 'package:flutter/material.dart';
import
'package:get/get.dart'
;
import
'package:get/get.dart'
;
import
'package:mypoint_flutter_app/screen/pageDetail/campaign_detail_screen.dart'
;
import
'package:mypoint_flutter_app/screen/pageDetail/campaign_detail_screen.dart'
;
import
'package:mypoint_flutter_app/widgets/back_button.dart'
;
import
'package:mypoint_flutter_app/widgets/back_button.dart'
;
import
'package:mypoint_flutter_app/widgets/custom_toast_message.dart'
;
import
'../../base/base_screen.dart'
;
import
'../../base/base_screen.dart'
;
import
'../../base/basic_state.dart'
;
import
'../../base/basic_state.dart'
;
import
'../../configs/constants.dart'
;
import
'../../resources/base_color.dart'
;
import
'../../resources/base_color.dart'
;
import
'../../shared/router_gage.dart'
;
import
'../../shared/router_gage.dart'
;
import
'../../widgets/custom_navigation_bar.dart'
;
import
'../../widgets/custom_navigation_bar.dart'
;
...
@@ -27,9 +29,6 @@ class _FAQScreenState extends BaseState<FAQScreen> with BasicState {
...
@@ -27,9 +29,6 @@ class _FAQScreenState extends BaseState<FAQScreen> with BasicState {
body:
Column
(
body:
Column
(
children:
[
children:
[
Obx
(()
{
Obx
(()
{
if
(
_controller
.
isLoading
.
value
)
{
return
const
Expanded
(
child:
Center
(
child:
CircularProgressIndicator
()));
}
if
(
_controller
.
faqItems
.
isEmpty
)
{
if
(
_controller
.
faqItems
.
isEmpty
)
{
return
const
Expanded
(
child:
Center
(
child:
Text
(
"Không có dữ liệu."
)));
return
const
Expanded
(
child:
Center
(
child:
Text
(
"Không có dữ liệu."
)));
}
}
...
@@ -50,12 +49,7 @@ class _FAQScreenState extends BaseState<FAQScreen> with BasicState {
...
@@ -50,12 +49,7 @@ class _FAQScreenState extends BaseState<FAQScreen> with BasicState {
if
(
item
.
pageId
!=
null
&&
item
.
pageId
!.
isNotEmpty
)
{
if
(
item
.
pageId
!=
null
&&
item
.
pageId
!.
isNotEmpty
)
{
Get
.
toNamed
(
campaignDetailScreen
,
arguments:
{
"id"
:
item
.
pageId
});
Get
.
toNamed
(
campaignDetailScreen
,
arguments:
{
"id"
:
item
.
pageId
});
}
else
{
}
else
{
Get
.
snackbar
(
showToastMessage
(
ErrorCodes
.
serverErrorMessage
);
"Thông báo"
,
"Không thể mở chi tiết vì thiếu ID!"
,
backgroundColor:
Colors
.
redAccent
,
colorText:
Colors
.
white
,
);
}
}
},
},
child:
Column
(
child:
Column
(
...
...
lib/screen/faqs/faqs_viewmodel.dart
View file @
0bf528a4
import
'dart:convert'
;
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'
;
import
'faqs_model.dart'
;
import
'faqs_model.dart'
;
class
FAQViewModel
extends
RestfulApiViewModel
{
class
FAQViewModel
extends
RestfulApiViewModel
{
var
faqItems
=
<
PageItemModel
>[].
obs
;
final
RxList
<
PageItemModel
>
faqItems
=
<
PageItemModel
>[].
obs
;
var
isLoading
=
true
.
obs
;
@override
@override
void
onInit
()
{
void
onInit
()
{
...
@@ -15,12 +13,14 @@ class FAQViewModel extends RestfulApiViewModel {
...
@@ -15,12 +13,14 @@ class FAQViewModel extends RestfulApiViewModel {
}
}
Future
<
void
>
fetchFAQItems
()
async
{
Future
<
void
>
fetchFAQItems
()
async
{
showLoading
();
await
callApi
<
FAQItemModelResponse
>(
isLoading
(
true
);
request:
()
=>
client
.
websiteFolderGetPageList
({
"folder_uri"
:
"FAQ"
}),
client
.
websiteFolderGetPageList
({
"folder_uri"
:
"FAQ"
}).
then
((
value
)
{
onSuccess:
(
data
,
_
)
{
hideLoading
();
faqItems
.
assignAll
(
data
.
items
??
[]);
isLoading
(
false
);
},
faqItems
.
value
=
value
.
data
?.
items
??
[];
onFailure:
(
_
,
_
,
_
)
async
{
});
faqItems
.
clear
();
},
);
}
}
}
}
lib/screen/game/game_tab_screen.dart
View file @
0bf528a4
...
@@ -67,9 +67,6 @@ class _GameTabScreenState extends BaseState<GameTabScreen> with BasicState, Popu
...
@@ -67,9 +67,6 @@ class _GameTabScreenState extends BaseState<GameTabScreen> with BasicState, Popu
],
],
),
),
body:
Obx
(()
{
body:
Obx
(()
{
if
(
_viewModel
.
isLoading
.
value
)
{
return
const
Center
(
child:
CircularProgressIndicator
());
}
if
(
_viewModel
.
games
.
isEmpty
)
{
if
(
_viewModel
.
games
.
isEmpty
)
{
return
const
Center
(
child:
EmptyWidget
());
return
const
Center
(
child:
EmptyWidget
());
}
}
...
...
lib/screen/game/game_tab_viewmodel.dart
View file @
0bf528a4
...
@@ -4,38 +4,36 @@ import 'package:mypoint_flutter_app/screen/game/models/game_bundle_item_model.da
...
@@ -4,38 +4,36 @@ import 'package:mypoint_flutter_app/screen/game/models/game_bundle_item_model.da
import
'../../networking/restful_api_viewmodel.dart'
;
import
'../../networking/restful_api_viewmodel.dart'
;
import
'../../configs/constants.dart'
;
import
'../../configs/constants.dart'
;
import
'models/game_bundle_response.dart'
;
class
GameTabViewModel
extends
RestfulApiViewModel
{
class
GameTabViewModel
extends
RestfulApiViewModel
{
final
RxList
<
GameBundleItemModel
>
games
=
<
GameBundleItemModel
>[].
obs
;
final
RxList
<
GameBundleItemModel
>
games
=
<
GameBundleItemModel
>[].
obs
;
var
turnsNumberText
=
""
.
obs
;
final
RxString
turnsNumberText
=
""
.
obs
;
var
isLoading
=
false
.
obs
;
void
Function
(
String
message
)?
onShowAlertError
;
void
Function
(
String
message
)?
onShowAlertError
;
void
Function
(
GameBundleItemModel
data
)?
gotoGameDetail
;
void
Function
(
GameBundleItemModel
data
)?
gotoGameDetail
;
void
getGames
()
{
void
getGames
()
{
isLoading
(
true
);
callApi
<
GameBundleResponse
>(
client
.
getGames
()
.
then
((
value
)
{
request:
()
=>
client
.
getGames
()
,
if
(!
value
.
isSuccess
)
{
onSuccess:
(
data
,
_
)
{
onShowAlertError
?.
call
(
value
.
errorMessage
??
Constants
.
commonError
);
games
.
assignAll
(
data
.
games
??
[]
);
}
else
{
turnsNumberText
.
value
=
data
.
turnsNumberText
??
""
;
games
.
value
=
value
.
data
?.
games
??
[];
},
turnsNumberText
.
value
=
value
.
data
?.
turnsNumberText
??
""
;
onFailure:
(
msg
,
_
,
_
)
async
{
}
onShowAlertError
?.
call
(
msg
);
isLoading
(
false
);
},
}
);
);
}
}
void
getGameDetail
(
String
gameId
)
{
void
getGameDetail
(
String
gameId
)
{
isLoading
(
true
);
callApi
<
GameBundleItemModel
>(
client
.
getGameDetail
(
gameId
).
then
((
value
)
{
request:
()
=>
client
.
getGameDetail
(
gameId
),
if
(!
value
.
isSuccess
)
{
onSuccess:
(
data
,
_
)
{
onShowAlertError
?.
call
(
value
.
errorMessage
??
Constants
.
commonError
);
gotoGameDetail
?.
call
(
data
);
}
else
if
(
value
.
data
!=
null
)
{
},
gotoGameDetail
?.
call
(
value
.
data
!);
onFailure:
(
msg
,
_
,
_
)
async
{
}
else
{
onShowAlertError
?.
call
(
msg
);
onShowAlertError
?.
call
(
Constants
.
commonError
);
},
}
);
isLoading
(
false
);
});
}
}
}
}
\ No newline at end of file
lib/screen/health_book/health_book_card_detail_viewmodel.dart
View file @
0bf528a4
...
@@ -5,17 +5,18 @@ import '../../networking/restful_api_viewmodel.dart';
...
@@ -5,17 +5,18 @@ import '../../networking/restful_api_viewmodel.dart';
import
'health_book_model.dart'
;
import
'health_book_model.dart'
;
class
HealthBookCardDetailViewModel
extends
RestfulApiViewModel
{
class
HealthBookCardDetailViewModel
extends
RestfulApiViewModel
{
var
card
=
Rxn
<
HealthBookCardItemModel
>();
final
Rxn
<
HealthBookCardItemModel
>
card
=
Rxn
<
HealthBookCardItemModel
>();
void
Function
(
String
message
)?
onShowAlertError
;
void
Function
(
String
message
)?
onShowAlertError
;
Future
<
void
>
getHealthBookCardDetail
(
String
cardId
)
async
{
Future
<
void
>
getHealthBookCardDetail
(
String
cardId
)
async
{
showLoading
();
await
callApi
<
HealthBookCardItemModel
>(
final
response
=
await
client
.
getDetailHealthBookCard
(
cardId
);
request:
()
=>
client
.
getDetailHealthBookCard
(
cardId
),
hideLoading
();
onSuccess:
(
data
,
_
)
{
if
(
response
.
isSuccess
)
{
card
.
value
=
data
;
card
.
value
=
response
.
data
;
},
}
else
{
onFailure:
(
msg
,
_
,
_
)
async
{
onShowAlertError
?.
call
(
response
.
errorMessage
??
Constants
.
commonError
);
onShowAlertError
?.
call
(
msg
);
}
},
);
}
}
}
}
\ No newline at end of file
lib/screen/health_book/health_book_viewmodel.dart
View file @
0bf528a4
...
@@ -6,10 +6,10 @@ import '../../networking/restful_api_viewmodel.dart';
...
@@ -6,10 +6,10 @@ import '../../networking/restful_api_viewmodel.dart';
import
'health_book_model.dart'
;
import
'health_book_model.dart'
;
class
HealthBookViewModel
extends
RestfulApiViewModel
{
class
HealthBookViewModel
extends
RestfulApiViewModel
{
var
healthBookData
=
Rxn
<
HealthBookResponseModel
>();
final
Rxn
<
HealthBookResponseModel
>
healthBookData
=
Rxn
<
HealthBookResponseModel
>();
var
healthBookDataDetail
=
Rxn
<
HealthBookCardItemModel
>();
final
Rxn
<
HealthBookCardItemModel
>
healthBookDataDetail
=
Rxn
<
HealthBookCardItemModel
>();
void
Function
(
String
message
)?
onShowAlertError
;
void
Function
(
String
message
)?
onShowAlertError
;
RxInt
selectedIndex
=
0
.
obs
;
final
RxInt
selectedIndex
=
0
.
obs
;
late
List
<
HeaderFilterOrderModel
>
headerFilterOrder
;
late
List
<
HeaderFilterOrderModel
>
headerFilterOrder
;
@override
@override
...
@@ -45,58 +45,14 @@ class HealthBookViewModel extends RestfulApiViewModel {
...
@@ -45,58 +45,14 @@ class HealthBookViewModel extends RestfulApiViewModel {
var
body
=
headerFilterOrder
[
selectedIndex
.
value
].
params
;
var
body
=
headerFilterOrder
[
selectedIndex
.
value
].
params
;
body
[
'page'
]
=
1
;
body
[
'page'
]
=
1
;
body
[
'size'
]
=
10000
;
body
[
'size'
]
=
10000
;
showLoading
();
await
callApi
<
HealthBookResponseModel
>(
try
{
request:
()
=>
client
.
getHealthBookCards
(
body
),
final
response
=
await
client
.
getHealthBookCards
(
body
);
onSuccess:
(
data
,
_
)
{
hideLoading
();
healthBookData
.
value
=
data
;
// var data = HealthBookResponseModel(total: 20, products: makeFakeHealthBookCards(20));
},
// healthBookData.value = data;
onFailure:
(
msg
,
_
,
_
)
async
{
if
(
response
.
isSuccess
)
{
onShowAlertError
?.
call
(
msg
);
healthBookData
.
value
=
response
.
data
;
},
}
else
{
);
onShowAlertError
?.
call
(
response
.
errorMessage
??
Constants
.
commonError
);
}
}
catch
(
error
)
{
hideLoading
();
onShowAlertError
?.
call
(
"Error fetching product detail:
$error
"
);
}
}
}
// Future<void> getDetailHealthBookCard(String id) async {
// showLoading();
// try {
// final response = await client.getDetailHealthBookCard(id);
// hideLoading();
// if (response.isSuccess) {
// healthBookDataDetail.value = response.data;
// } else {
// onShowAlertError?.call(response.errorMessage ?? Constants.commonError);
// }
// } catch (error) {
// hideLoading();
// onShowAlertError?.call("Error fetching product detail: $error");
// }
// }
// List<HealthBookCardItemModel> makeFakeHealthBookCards(int n) {
// return List.generate(n, (i) {
// final id = 2000 + i;
// return HealthBookCardItemModel(
// itemId: id,
// cardName: 'Thẻ Khám #$id',
// fullName: 'User #$id',
// cardCode: 'MP-${id.toString().padLeft(4, '0')}',
// expireDate: '2025-12-31T00:00:00Z',
// phoneNumber: '09${(10000000 + i).toString().padLeft(8, '0')}',
// updatedAt: '2025-10-10T10:00:00Z',
// countCheckupUnused: i % 6,
// bottomButton: ButtonConfigModel(text: 'Sử dụng', action: 'use'),
// media: [
// ProductMediaItem(url: 'https://picsum.photos/seed/$id/300/300'),
// ],
// buyMoreNote: ButtonConfigModel(text: 'Mua thêm', action: 'buy_more'),
// active: ActiveTextConfig(text: 'Còn hiệu lực', textColor: '#0F9D58', bgColor: '#E6F4EA'),
// );
// });
// }
}
}
\ No newline at end of file
lib/screen/health_book/widgets/health_book_item.dart
View file @
0bf528a4
...
@@ -119,3 +119,4 @@ class HealthBookItem extends StatelessWidget {
...
@@ -119,3 +119,4 @@ class HealthBookItem extends StatelessWidget {
);
);
}
}
}
}
lib/screen/history_point/history_point_chart.dart
View file @
0bf528a4
...
@@ -3,6 +3,7 @@ import 'dart:math';
...
@@ -3,6 +3,7 @@ import 'dart:math';
import
'package:flutter/material.dart'
;
import
'package:flutter/material.dart'
;
import
'package:fl_chart/fl_chart.dart'
;
import
'package:fl_chart/fl_chart.dart'
;
import
'package:intl/intl.dart'
;
import
'package:intl/intl.dart'
;
import
'package:mypoint_flutter_app/extensions/num_extension.dart'
;
import
'models/transaction_summary_by_date_model.dart'
;
import
'models/transaction_summary_by_date_model.dart'
;
class
MonthlyPointsChart
extends
StatelessWidget
{
class
MonthlyPointsChart
extends
StatelessWidget
{
...
@@ -26,12 +27,21 @@ class MonthlyPointsChart extends StatelessWidget {
...
@@ -26,12 +27,21 @@ class MonthlyPointsChart extends StatelessWidget {
@override
@override
Widget
build
(
BuildContext
context
)
{
Widget
build
(
BuildContext
context
)
{
print
(
'🔍 MonthlyPointsChart Debug:'
);
print
(
' - items.length:
${items.length}
'
);
print
(
' - date:
$date
'
);
print
(
' - monthSummary:
$monthSummary
'
);
for
(
int
i
=
0
;
i
<
items
.
length
;
i
++)
{
print
(
' - items[
$i
]:
${items[i].summaryDate}
-> reward:
${items[i].rewardDayTotal}
'
);
}
final
parsed
=
_parseToDayMap
(
items
,
date
);
final
parsed
=
_parseToDayMap
(
items
,
date
);
print
(
'
items
${items.length}
,
parsed:
$parsed
'
);
print
(
'
-
parsed
map
:
$parsed
'
);
final
daysInMonth
=
DateUtils
.
getDaysInMonth
(
date
.
year
,
date
.
month
);
final
daysInMonth
=
DateUtils
.
getDaysInMonth
(
date
.
year
,
date
.
month
);
final
maxVal
=
(
parsed
.
values
.
isEmpty
?
0
:
parsed
.
values
.
reduce
((
a
,
b
)
=>
a
>
b
?
a
:
b
)
).
abs
()
;
final
maxVal
=
parsed
.
values
.
isEmpty
?
0
:
parsed
.
values
.
reduce
((
a
,
b
)
=>
a
>
b
?
a
:
b
);
final
yMax
=
_niceMax
(
maxVal
.
toDouble
());
final
yMax
=
_niceMax
(
maxVal
.
abs
().
toDouble
());
final
yStep
=
_niceStep
(
yMax
);
final
yStep
=
_niceStep
(
yMax
);
final
stats
=
_statsByDay
(
items
,
date
);
final
stats
=
_statsByDay
(
items
,
date
);
final
barGroups
=
List
.
generate
(
daysInMonth
,
(
i
)
{
final
barGroups
=
List
.
generate
(
daysInMonth
,
(
i
)
{
final
day
=
i
+
1
;
final
day
=
i
+
1
;
...
@@ -42,6 +52,12 @@ class MonthlyPointsChart extends StatelessWidget {
...
@@ -42,6 +52,12 @@ class MonthlyPointsChart extends StatelessWidget {
barRods:
[
BarChartRodData
(
toY:
v
,
width:
8
,
borderRadius:
BorderRadius
.
circular
(
2
),
color:
color
)],
barRods:
[
BarChartRodData
(
toY:
v
,
width:
8
,
borderRadius:
BorderRadius
.
circular
(
2
),
color:
color
)],
);
);
});
});
print
(
' - daysInMonth:
$daysInMonth
'
);
print
(
' - maxVal:
$maxVal
'
);
print
(
' - yMax:
$yMax
'
);
print
(
' - yStep:
$yStep
'
);
print
(
' - barGroups.length:
${barGroups.length}
'
);
return
Container
(
return
Container
(
decoration:
BoxDecoration
(
decoration:
BoxDecoration
(
...
@@ -62,7 +78,7 @@ class MonthlyPointsChart extends StatelessWidget {
...
@@ -62,7 +78,7 @@ class MonthlyPointsChart extends StatelessWidget {
mainAxisAlignment:
MainAxisAlignment
.
center
,
mainAxisAlignment:
MainAxisAlignment
.
center
,
children:
[
children:
[
Text
(
Text
(
_formatInt
(
_toDouble
(
monthSummary
?.
rewardMonthTotal
??
'0'
)),
_toDouble
(
monthSummary
?.
rewardMonthTotal
??
'0'
)
.
money
(
CurrencyUnit
.
noneSpace
),
style:
const
TextStyle
(
style:
const
TextStyle
(
fontSize:
40
,
fontSize:
40
,
fontWeight:
FontWeight
.
w700
,
fontWeight:
FontWeight
.
w700
,
...
@@ -80,19 +96,19 @@ class MonthlyPointsChart extends StatelessWidget {
...
@@ -80,19 +96,19 @@ class MonthlyPointsChart extends StatelessWidget {
child:
BarChart
(
child:
BarChart
(
BarChartData
(
BarChartData
(
minY:
0
,
minY:
0
,
maxY:
yMax
,
maxY:
yMax
>
0
?
yMax
:
10
,
// Đảm bảo có giá trị tối thiểu
barGroups:
barGroups
,
barGroups:
barGroups
,
gridData:
FlGridData
(
gridData:
FlGridData
(
show:
true
,
show:
true
,
drawVerticalLine:
false
,
drawVerticalLine:
false
,
horizontalInterval:
yStep
,
horizontalInterval:
yStep
>
0
?
yStep
:
2
,
getDrawingHorizontalLine:
(
v
)
=>
FlLine
(
color:
Colors
.
black12
,
strokeWidth:
1
),
getDrawingHorizontalLine:
(
v
)
=>
FlLine
(
color:
Colors
.
black12
,
strokeWidth:
1
),
),
),
extraLinesData:
ExtraLinesData
(
extraLinesData:
ExtraLinesData
(
extraLinesOnTop:
true
,
extraLinesOnTop:
true
,
horizontalLines:
[
horizontalLines:
[
HorizontalLine
(
y:
0
,
color:
Colors
.
black12
,
strokeWidth:
1
),
HorizontalLine
(
y:
0
,
color:
Colors
.
black12
,
strokeWidth:
1
),
HorizontalLine
(
y:
yMax
,
color:
Colors
.
black12
,
strokeWidth:
1
),
HorizontalLine
(
y:
yMax
>
0
?
yMax
:
10
,
color:
Colors
.
black12
,
strokeWidth:
1
),
],
],
),
),
titlesData:
FlTitlesData
(
titlesData:
FlTitlesData
(
...
@@ -100,14 +116,22 @@ class MonthlyPointsChart extends StatelessWidget {
...
@@ -100,14 +116,22 @@ class MonthlyPointsChart extends StatelessWidget {
rightTitles:
const
AxisTitles
(
sideTitles:
SideTitles
(
showTitles:
false
)),
rightTitles:
const
AxisTitles
(
sideTitles:
SideTitles
(
showTitles:
false
)),
leftTitles:
AxisTitles
(
leftTitles:
AxisTitles
(
sideTitles:
SideTitles
(
sideTitles:
SideTitles
(
reservedSize:
28
,
reservedSize:
40
,
// Tăng độ rộng để chứa text dài
showTitles:
true
,
showTitles:
true
,
interval:
yStep
,
interval:
yStep
>
0
?
yStep
:
2
,
getTitlesWidget:
getTitlesWidget:
(
value
,
meta
)
{
(
value
,
meta
)
=>
Text
(
final
text
=
_formatYAxisLabel
(
value
.
toInt
());
value
.
toInt
().
toString
(),
return
SizedBox
(
style:
const
TextStyle
(
fontSize:
10
,
color:
Colors
.
black54
),
width:
35
,
// Cố định độ rộng
child:
Text
(
text
,
style:
const
TextStyle
(
fontSize:
9
,
color:
Colors
.
black54
),
textAlign:
TextAlign
.
right
,
maxLines:
1
,
overflow:
TextOverflow
.
ellipsis
,
),
),
);
},
),
),
),
),
bottomTitles:
AxisTitles
(
bottomTitles:
AxisTitles
(
...
@@ -143,7 +167,7 @@ class MonthlyPointsChart extends StatelessWidget {
...
@@ -143,7 +167,7 @@ class MonthlyPointsChart extends StatelessWidget {
return
BarTooltipItem
(
return
BarTooltipItem
(
textAlign:
TextAlign
.
center
,
textAlign:
TextAlign
.
center
,
'Ngày
$day
/
${date.month}
\n
'
'Ngày
$day
/
${date.month}
\n
'
'Tích điểm:
${
_formatInt(r
)}
'
,
'Tích điểm:
${
r.money(CurrencyUnit.noneSpace
)}
'
,
const
TextStyle
(
color:
Colors
.
white
,
fontSize:
12
,
fontWeight:
FontWeight
.
w500
),
const
TextStyle
(
color:
Colors
.
white
,
fontSize:
12
,
fontWeight:
FontWeight
.
w500
),
);
);
},
},
...
@@ -222,12 +246,31 @@ class MonthlyPointsChart extends StatelessWidget {
...
@@ -222,12 +246,31 @@ class MonthlyPointsChart extends StatelessWidget {
}
}
static
String
_formatInt
(
double
v
)
=>
v
.
toStringAsFixed
(
0
);
static
String
_formatInt
(
double
v
)
=>
v
.
toStringAsFixed
(
0
);
/// Format Y-axis label để hiển thị gọn gàng
String
_formatYAxisLabel
(
int
value
)
{
if
(
value
>=
1000000
)
{
return
'
${(value / 1000000).toStringAsFixed(1)}
M'
;
}
else
if
(
value
>=
1000
)
{
return
'
${(value / 1000).toStringAsFixed(0)}
K'
;
}
else
{
return
value
.
toString
();
}
}
/// Làm tròn max Y cho đẹp (bước 4/5)
/// Làm tròn max Y cho đẹp (bước 4/5)
double
_niceMax
(
double
maxVal
)
{
double
_niceMax
(
double
maxVal
)
{
if
(
maxVal
<=
0
)
return
10
;
if
(
maxVal
<=
0
)
return
10
;
// làm tròn lên tới bội số 4 hoặc 5 gần nhất
final
candidates
=
[
4
,
5
,
10
];
// Xử lý giá trị lớn (> 1000)
if
(
maxVal
>
1000
)
{
// Làm tròn lên đến bội số 1000 gần nhất
final
up
=
((
maxVal
/
1000
).
ceil
())
*
1000
;
return
up
.
toDouble
();
}
// Xử lý giá trị nhỏ (< 1000)
final
candidates
=
[
4
,
5
,
10
,
20
,
50
,
100
];
for
(
final
step
in
candidates
)
{
for
(
final
step
in
candidates
)
{
final
up
=
((
maxVal
/
step
).
ceil
())
*
step
;
final
up
=
((
maxVal
/
step
).
ceil
())
*
step
;
if
(
up
>=
maxVal
&&
up
/
step
<=
6
)
return
up
.
toDouble
();
// tối đa 6 vạch cho gọn
if
(
up
>=
maxVal
&&
up
/
step
<=
6
)
return
up
.
toDouble
();
// tối đa 6 vạch cho gọn
...
@@ -239,7 +282,16 @@ class MonthlyPointsChart extends StatelessWidget {
...
@@ -239,7 +282,16 @@ class MonthlyPointsChart extends StatelessWidget {
if
(
yMax
<=
10
)
return
2
;
// 0,2,4,6,8,10
if
(
yMax
<=
10
)
return
2
;
// 0,2,4,6,8,10
if
(
yMax
<=
20
)
return
4
;
// 0,4,8,12,16,20
if
(
yMax
<=
20
)
return
4
;
// 0,4,8,12,16,20
if
(
yMax
<=
50
)
return
10
;
if
(
yMax
<=
50
)
return
10
;
return
20
;
if
(
yMax
<=
100
)
return
20
;
if
(
yMax
<=
500
)
return
50
;
if
(
yMax
<=
1000
)
return
100
;
if
(
yMax
<=
5000
)
return
500
;
if
(
yMax
<=
10000
)
return
1000
;
if
(
yMax
<=
50000
)
return
5000
;
if
(
yMax
<=
100000
)
return
10000
;
if
(
yMax
<=
500000
)
return
50000
;
if
(
yMax
<=
1000000
)
return
100000
;
return
200000
;
// cho giá trị rất lớn
}
}
Map
<
int
,
_DayStat
>
_statsByDay
(
List
<
DaySummaryChartModel
>
list
,
DateTime
month
)
{
Map
<
int
,
_DayStat
>
_statsByDay
(
List
<
DaySummaryChartModel
>
list
,
DateTime
month
)
{
...
...
lib/screen/history_point/history_point_screen.dart
View file @
0bf528a4
...
@@ -202,7 +202,7 @@ class _HistoryPointScreenState extends State<HistoryPointScreen> {
...
@@ -202,7 +202,7 @@ class _HistoryPointScreenState extends State<HistoryPointScreen> {
final
adjustTotal
=
item
.
adjustTotal
?.
toInt
()
??
0
;
final
adjustTotal
=
item
.
adjustTotal
?.
toInt
()
??
0
;
final
value
=
rewardTotal
-
redeemTotal
+
adjustTotal
;
final
value
=
rewardTotal
-
redeemTotal
+
adjustTotal
;
final
valueColor
=
value
>=
0
?
const
Color
(
0xFF21C777
)
:
const
Color
(
0xFFFE515A
);
final
valueColor
=
value
>=
0
?
const
Color
(
0xFF21C777
)
:
const
Color
(
0xFFFE515A
);
final
valueText
=
'
${value > 0 ? '+' : (value < 0 ? '-' : '')}${value.
toInt(
)}
'
;
final
valueText
=
'
${value > 0 ? '+' : (value < 0 ? '-' : '')}${value.
money(CurrencyUnit.noneSpace
)}
'
;
final
dateText
=
item
.
transactionDatetime
?.
toDate
()?.
toFormattedString
(
format:
DateFormat
.
viFull
);
final
dateText
=
item
.
transactionDatetime
?.
toDate
()?.
toFormattedString
(
format:
DateFormat
.
viFull
);
final
transactionId
=
item
.
transactionSequenceId
.
orIfBlank
(
''
);
final
transactionId
=
item
.
transactionSequenceId
.
orIfBlank
(
''
);
return
InkWell
(
return
InkWell
(
...
...
lib/screen/history_point/history_point_viewmodel.dart
View file @
0bf528a4
...
@@ -40,7 +40,7 @@ class HistoryPointViewModel extends RestfulApiViewModel {
...
@@ -40,7 +40,7 @@ class HistoryPointViewModel extends RestfulApiViewModel {
onSuccess:
(
data
,
_
)
{
onSuccess:
(
data
,
_
)
{
transactionSummary
.
value
=
data
;
transactionSummary
.
value
=
data
;
},
},
onFailure:
(
msg
,
_
,
_
_
)
async
{
onFailure:
(
msg
,
_
,
_
)
async
{
transactionSummary
.
value
=
null
;
transactionSummary
.
value
=
null
;
},
},
);
);
...
@@ -62,7 +62,7 @@ class HistoryPointViewModel extends RestfulApiViewModel {
...
@@ -62,7 +62,7 @@ class HistoryPointViewModel extends RestfulApiViewModel {
onSuccess:
(
data
,
_
)
{
onSuccess:
(
data
,
_
)
{
historyPoint
.
value
=
data
;
historyPoint
.
value
=
data
;
},
},
onFailure:
(
msg
,
_
,
_
_
)
async
{
onFailure:
(
msg
,
_
,
_
)
async
{
historyPoint
.
value
=
null
;
historyPoint
.
value
=
null
;
},
},
);
);
...
...
lib/screen/history_point_cashback/history_point_cashback_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/extensions/collection_extension.dart'
;
import
'package:mypoint_flutter_app/extensions/collection_extension.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
'models/history_point_cashback_model.dart'
;
import
'models/history_point_cashback_model.dart'
;
class
HistoryPointCashBackViewModel
extends
RestfulApiViewModel
{
class
HistoryPointCashBackViewModel
extends
RestfulApiViewModel
{
late
List
<
CashBackPointOrderStatus
>
tagStatus
;
late
List
<
CashBackPointOrderStatus
>
tagStatus
;
CashBackPointOrderStatus
get
selectedTag
{
CashBackPointOrderStatus
get
selectedTag
=>
tagStatus
.
safe
(
selectedTabIndex
.
value
)
??
CashBackPointOrderStatus
.
pending
;
return
tagStatus
.
safe
(
selectedTabIndex
.
value
)
??
CashBackPointOrderStatus
.
pending
;
}
final
RxInt
selectedTabIndex
=
0
.
obs
;
final
RxInt
selectedTabIndex
=
0
.
obs
;
var
pointCashBackData
=
Rxn
<
HistoryPointCashBackResponse
>();
final
Rxn
<
HistoryPointCashBackResponse
>
pointCashBackData
=
Rxn
<
HistoryPointCashBackResponse
>();
List
<
HistoryPointCashBackOrderModel
>
get
orders
{
List
<
HistoryPointCashBackOrderModel
>
get
orders
=>
pointCashBackData
.
value
?.
orders
??
[];
return
pointCashBackData
.
value
?.
orders
??
[];
}
int
_page
=
1
;
int
_page
=
1
;
...
@@ -31,28 +26,23 @@ class HistoryPointCashBackViewModel extends RestfulApiViewModel {
...
@@ -31,28 +26,23 @@ class HistoryPointCashBackViewModel extends RestfulApiViewModel {
freshData
(
isRefresh:
true
);
freshData
(
isRefresh:
true
);
}
}
void
freshData
({
bool
isRefresh
=
false
})
{
Future
<
void
>
freshData
({
bool
isRefresh
=
false
})
async
{
if
(
isRefresh
)
{
_page
=
isRefresh
?
1
:
_page
+
1
;
_page
=
1
;
}
else
{
_page
+=
1
;
}
final
body
=
{
"page"
:
_page
,
"size"
:
20
,
"type"
:
selectedTag
.
rawValue
};
final
body
=
{
"page"
:
_page
,
"size"
:
20
,
"type"
:
selectedTag
.
rawValue
};
client
await
callApi
<
HistoryPointCashBackResponse
>(
.
historyPointCashBackRequest
(
body
)
request:
()
=>
client
.
historyPointCashBackRequest
(
body
),
.
then
((
response
)
{
onSuccess:
(
data
,
_
)
{
final
result
=
response
.
data
;
if
(
isRefresh
)
{
if
(
isRefresh
)
{
pointCashBackData
.
value
=
data
;
pointCashBackData
.
value
=
result
;
}
else
{
}
else
{
final
next
=
data
.
orders
??
[];
final
orders
=
result
?.
orders
??
[];
pointCashBackData
.
value
?.
orders
?.
addAll
(
next
);
pointCashBackData
.
value
?.
orders
?.
addAll
(
orders
);
pointCashBackData
.
refresh
();
pointCashBackData
.
refresh
();
}
}
},
})
onFailure:
(
_
,
_
,
_
)
async
{},
.
catchError
((
error
)
{
withLoading:
isRefresh
,
print
(
'Error fetching products:
$error
'
);
);
});
}
}
void
selectTab
(
int
index
)
{
void
selectTab
(
int
index
)
{
...
...
lib/screen/home/custom_widget/header_home_widget.dart
View file @
0bf528a4
...
@@ -20,7 +20,6 @@ class HomeGreetingHeader extends StatelessWidget {
...
@@ -20,7 +20,6 @@ class HomeGreetingHeader extends StatelessWidget {
final
heightSize
=
heightContent
??
(
width
*
86
/
375
+
112
);
final
heightSize
=
heightContent
??
(
width
*
86
/
375
+
112
);
final
name
=
DataPreference
.
instance
.
displayName
;
final
name
=
DataPreference
.
instance
.
displayName
;
final
level
=
DataPreference
.
instance
.
rankName
??
"Hạng Đồng"
;
final
level
=
DataPreference
.
instance
.
rankName
??
"Hạng Đồng"
;
final
double
statusBarHeight
=
MediaQuery
.
of
(
context
).
padding
.
top
;
final
double
heightWhiteBox
=
112
;
final
double
heightWhiteBox
=
112
;
return
Stack
(
return
Stack
(
...
@@ -149,23 +148,23 @@ class HomeGreetingHeader extends StatelessWidget {
...
@@ -149,23 +148,23 @@ class HomeGreetingHeader extends StatelessWidget {
);
);
}
}
_onSearchTap
()
{
void
_onSearchTap
()
{
Get
.
toNamed
(
vouchersScreen
,
arguments:
{
"enableSearch"
:
true
});
Get
.
toNamed
(
vouchersScreen
,
arguments:
{
"enableSearch"
:
true
});
}
}
_onNotificationTap
()
{
void
_onNotificationTap
()
{
Get
.
toNamed
(
notificationScreen
);
Get
.
toNamed
(
notificationScreen
);
}
}
_onPointTap
()
{
void
_onPointTap
()
{
Get
.
toNamed
(
historyPointScreen
);
Get
.
toNamed
(
historyPointScreen
);
}
}
_onMyVoucherTap
()
{
void
_onMyVoucherTap
()
{
Get
.
toNamed
(
myVoucherListScreen
);
Get
.
toNamed
(
myVoucherListScreen
);
}
}
_onRankTap
()
{
void
_onRankTap
()
{
Get
.
toNamed
(
membershipScreen
);
Get
.
toNamed
(
membershipScreen
);
}
}
}
}
lib/screen/home/header_home_viewmodel.dart
View file @
0bf528a4
...
@@ -11,7 +11,7 @@ class HeaderThemeController extends GetxController {
...
@@ -11,7 +11,7 @@ class HeaderThemeController extends GetxController {
class
HeaderHomeViewModel
extends
RestfulApiViewModel
{
class
HeaderHomeViewModel
extends
RestfulApiViewModel
{
final
Rx
<
HeaderHomeModel
?>
_headerHomeData
=
Rx
<
HeaderHomeModel
?>(
null
);
final
Rx
<
HeaderHomeModel
?>
_headerHomeData
=
Rx
<
HeaderHomeModel
?>(
null
);
var
notificationUnreadData
=
Rxn
<
NotificationUnreadData
>();
final
Rxn
<
NotificationUnreadData
>
notificationUnreadData
=
Rxn
<
NotificationUnreadData
>();
HeaderHomeModel
get
headerData
{
HeaderHomeModel
get
headerData
{
return
_headerHomeData
.
value
??
return
_headerHomeData
.
value
??
...
@@ -32,21 +32,23 @@ class HeaderHomeViewModel extends RestfulApiViewModel {
...
@@ -32,21 +32,23 @@ class HeaderHomeViewModel extends RestfulApiViewModel {
}
}
Future
<
void
>
_getDynamicHeaderHome
()
async
{
Future
<
void
>
_getDynamicHeaderHome
()
async
{
try
{
await
callApi
<
HeaderHomeModel
>(
final
result
=
await
client
.
getDynamicHeaderHome
();
request:
()
=>
client
.
getDynamicHeaderHome
(),
_headerHomeData
.
value
=
result
.
data
;
onSuccess:
(
data
,
_
)
{
Get
.
find
<
HeaderThemeController
>().
setBackground
(
_headerHomeData
.
value
?.
background
);
_headerHomeData
.
value
=
data
;
}
catch
(
error
)
{
Get
.
find
<
HeaderThemeController
>().
setBackground
(
_headerHomeData
.
value
?.
background
);
print
(
"Error fetching getDynamicHeaderHome:
$error
"
);
},
}
withLoading:
false
,
);
}
}
Future
<
void
>
_getNotificationUnread
()
async
{
Future
<
void
>
_getNotificationUnread
()
async
{
try
{
await
callApi
<
NotificationUnreadData
>(
final
result
=
await
client
.
getNotificationUnread
();
request:
()
=>
client
.
getNotificationUnread
(),
notificationUnreadData
.
value
=
result
.
data
;
onSuccess:
(
data
,
_
)
{
}
catch
(
error
)
{
notificationUnreadData
.
value
=
data
;
print
(
"Error fetching hot products:
$error
"
);
},
}
withLoading:
false
,
);
}
}
}
}
lib/screen/home/home_screen.dart
View file @
0bf528a4
...
@@ -6,7 +6,6 @@ import 'package:mypoint_flutter_app/screen/pipi/pipi_detail_screen.dart';
...
@@ -6,7 +6,6 @@ import 'package:mypoint_flutter_app/screen/pipi/pipi_detail_screen.dart';
import
'package:mypoint_flutter_app/screen/voucher/models/product_model.dart'
;
import
'package:mypoint_flutter_app/screen/voucher/models/product_model.dart'
;
import
'package:mypoint_flutter_app/shared/router_gage.dart'
;
import
'package:mypoint_flutter_app/shared/router_gage.dart'
;
import
'../../directional/directional_action_type.dart'
;
import
'../../directional/directional_action_type.dart'
;
import
'../../directional/directional_screen.dart'
;
import
'../popup_manager/popup_runner_helper.dart'
;
import
'../popup_manager/popup_runner_helper.dart'
;
import
'custom_widget/achievement_carousel_widget.dart'
;
import
'custom_widget/achievement_carousel_widget.dart'
;
import
'custom_widget/affiliate_brand_grid_widget.dart'
;
import
'custom_widget/affiliate_brand_grid_widget.dart'
;
...
...
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