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
89983084
Commit
89983084
authored
Oct 16, 2025
by
DatHV
Browse files
update logic. refactor code
parent
928c3660
Changes
22
Hide whitespace changes
Inline
Side-by-side
lib/base/app_loading.dart
View file @
89983084
...
...
@@ -58,7 +58,7 @@ class AppLoading {
}
void
show
({
Duration
timeout
=
const
Duration
(
seconds:
Constants
.
loadingT
imeoutSeconds
),
Duration
timeout
=
const
Duration
(
seconds:
Constants
.
t
imeoutSeconds
),
Color
?
barrierColor
=
const
Color
(
0x33000000
),
bool
absorbPointers
=
true
,
double
size
=
56
,
...
...
lib/base/base_view_model.dart
View file @
89983084
...
...
@@ -37,21 +37,8 @@ class BaseViewModel extends GetxController with WidgetsBindingObserver {
}
}
void
showProgressIndicator
()
{
Get
.
dialog
(
const
Center
(
child:
CircularProgressIndicator
()),
barrierDismissible:
false
,
);
}
void
hideProgressIndicator
()
{
if
(
Get
.
isDialogOpen
??
false
)
{
Get
.
back
();
}
}
void
showLoading
({
int
timeout
=
Constants
.
loadingTimeoutSeconds
})
{
AppLoading
().
show
(
timeout:
Duration
(
seconds:
timeout
));
void
showLoading
()
{
AppLoading
().
show
();
}
void
hideLoading
()
{
...
...
lib/configs/constants.dart
View file @
89983084
...
...
@@ -4,8 +4,7 @@ class Constants {
static
var
otpTtl
=
180
;
static
var
directionInApp
=
"IN-APP"
;
static
var
phoneNumberCount
=
10
;
static
var
timeoutSeconds
=
30
;
static
const
loadingTimeoutSeconds
=
30
;
static
const
timeoutSeconds
=
30
;
static
const
appStoreId
=
'1495923300'
;
}
...
...
lib/networking/interceptor/logger_interceptor.dart
View file @
89983084
import
'dart:convert'
;
import
'package:dio/dio.dart'
;
import
'package:logger/logger.dart'
;
class
LoggerInterceptor
extends
Interceptor
{
// Configs
final
bool
prettyPrintJson
=
false
;
// Mặc định: JSON 1 dòng dễ copy/paste
final
bool
chunkLogging
=
true
;
// Chia nhỏ log theo block để tránh bị cắt
final
int
chunkSize
=
800
;
// Kích thước mỗi block
final
Logger
_logger
=
Logger
(
printer:
PrettyPrinter
(
methodCount:
0
,
...
...
@@ -14,12 +20,17 @@ class LoggerInterceptor extends Interceptor {
@override
void
onRequest
(
RequestOptions
options
,
RequestInterceptorHandler
handler
)
{
final
uri
=
options
.
uri
;
_logger
.
i
(
'🚀
${options.method}
$uri
\n
'
'Headers:
${_formatHeaders(options.headers)}
\n
'
'Query:
${options.queryParameters}
\n
'
'Body:
${_formatData(options.data)}
'
,
);
final
buffer
=
StringBuffer
();
buffer
.
writeln
(
'🚀
${options.method}
$uri
'
);
buffer
.
writeln
(
'Headers:
${_formatHeaders(options.headers)}
'
);
if
(
options
.
queryParameters
.
isNotEmpty
)
{
buffer
.
writeln
(
'Query:
${_stringify(options.queryParameters)}
'
);
}
_emit
(
Level
.
info
,
'REQUEST'
,
uri
.
toString
(),
buffer
.
toString
());
if
(
options
.
data
!=
null
)
{
final
bodyString
=
_stringify
(
options
.
data
);
_emitJsonBlocks
(
Level
.
info
,
'REQUEST JSON'
,
uri
.
toString
(),
bodyString
);
}
handler
.
next
(
options
);
}
...
...
@@ -27,10 +38,15 @@ class LoggerInterceptor extends Interceptor {
void
onResponse
(
Response
response
,
ResponseInterceptorHandler
handler
)
{
final
uri
=
response
.
requestOptions
.
uri
;
final
statusCode
=
response
.
statusCode
;
_logger
.
d
(
'✅
$statusCode
${response.requestOptions.method}
$uri
\n
'
'Response:
${_formatData(response.data)}
'
,
);
final
buffer
=
StringBuffer
();
buffer
.
writeln
(
'✅
$statusCode
${response.requestOptions.method}
$uri
'
);
if
(
response
.
headers
.
map
.
isNotEmpty
)
{
buffer
.
writeln
(
'Resp Headers:
${_stringify(response.headers.map)}
'
);
}
_emit
(
Level
.
debug
,
'RESPONSE'
,
uri
.
toString
(),
buffer
.
toString
());
// emit body in copy-friendly blocks
final
bodyString
=
_stringify
(
response
.
data
);
_emitJsonBlocks
(
Level
.
debug
,
'RESPONSE JSON'
,
uri
.
toString
(),
bodyString
);
handler
.
next
(
response
);
}
...
...
@@ -38,11 +54,14 @@ class LoggerInterceptor extends Interceptor {
void
onError
(
DioException
err
,
ErrorInterceptorHandler
handler
)
{
final
uri
=
err
.
requestOptions
.
uri
;
final
statusCode
=
err
.
response
?.
statusCode
??
'Unknown'
;
_logger
.
e
(
'❌
$statusCode
${err.requestOptions.method}
$uri
\n
'
'Error:
${err.message}
\n
'
'Response:
${_formatData(err.response?.data)}
'
,
);
final
buffer
=
StringBuffer
();
buffer
.
writeln
(
'❌
$statusCode
${err.requestOptions.method}
$uri
'
);
buffer
.
writeln
(
'Error:
${err.message}
'
);
_emit
(
Level
.
error
,
'ERROR'
,
uri
.
toString
(),
buffer
.
toString
());
if
(
err
.
response
?.
data
!=
null
)
{
final
bodyString
=
_stringify
(
err
.
response
?.
data
);
_emitJsonBlocks
(
Level
.
error
,
'ERROR JSON'
,
uri
.
toString
(),
bodyString
);
}
handler
.
next
(
err
);
}
...
...
@@ -55,11 +74,47 @@ class LoggerInterceptor extends Interceptor {
return
filtered
.
toString
();
}
String
_
formatData
(
dynamic
data
)
{
String
_
stringify
(
dynamic
data
)
{
if
(
data
==
null
)
return
'null'
;
if
(
data
is
String
&&
data
.
length
>
1000
)
{
return
'
${data.substring(0, 1000)}
... (truncated)'
;
if
(
data
is
String
)
return
data
;
try
{
if
(
prettyPrintJson
)
{
final
encoder
=
const
JsonEncoder
.
withIndent
(
' '
);
return
encoder
.
convert
(
data
);
}
return
jsonEncode
(
data
);
}
catch
(
_
)
{
return
data
.
toString
();
}
}
void
_emit
(
Level
level
,
String
phase
,
String
uri
,
String
message
)
{
if
(!
chunkLogging
||
message
.
length
<=
chunkSize
)
{
_logger
.
log
(
level
,
'[
$phase
]
$uri
\n
$message
'
);
return
;
}
final
total
=
(
message
.
length
/
chunkSize
).
ceil
();
var
index
=
0
;
for
(
var
i
=
0
;
i
<
message
.
length
;
i
+=
chunkSize
)
{
final
end
=
(
i
+
chunkSize
<
message
.
length
)
?
i
+
chunkSize
:
message
.
length
;
index
+=
1
;
_logger
.
log
(
level
,
'[
$phase
PART
$index
/
$total
]
$uri
\n
${message.substring(i, end)}
'
);
}
}
void
_emitJsonBlocks
(
Level
level
,
String
phase
,
String
uri
,
String
jsonText
)
{
if
(!
chunkLogging
||
jsonText
.
length
<=
chunkSize
)
{
_logger
.
log
(
level
,
'[
$phase
FULL]
$uri
'
);
_logger
.
log
(
level
,
jsonText
);
return
;
}
final
total
=
(
jsonText
.
length
/
chunkSize
).
ceil
();
var
index
=
0
;
for
(
var
i
=
0
;
i
<
jsonText
.
length
;
i
+=
chunkSize
)
{
final
end
=
(
i
+
chunkSize
<
jsonText
.
length
)
?
i
+
chunkSize
:
jsonText
.
length
;
index
+=
1
;
_logger
.
log
(
level
,
'[
$phase
PART
$index
/
$total
]
$uri
'
);
_logger
.
log
(
level
,
jsonText
.
substring
(
i
,
end
));
}
return
data
.
toString
();
}
}
\ No newline at end of file
lib/screen/achievement/achievement_viewmodel.dart
View file @
89983084
...
...
@@ -5,8 +5,9 @@ import '../../preference/data_preference.dart';
import
'../home/models/achievement_model.dart'
;
class
AchievementViewModel
extends
RestfulApiViewModel
{
bool
isPointHunting
;
var
achievements
=
<
AchievementModel
>[].
obs
;
final
bool
isPointHunting
;
final
RxList
<
AchievementModel
>
achievements
=
<
AchievementModel
>[].
obs
;
AchievementViewModel
({
this
.
isPointHunting
=
false
});
@override
...
...
@@ -23,12 +24,16 @@ class AchievementViewModel extends RestfulApiViewModel {
"start"
:
0
,
"limit"
:
1000
,
};
await
callApi
<
AchievementListResponse
>(
request:
()
=>
client
.
getAchievementList
(
body
),
onSuccess:
(
data
,
_
)
{
achievements
.
value
=
data
.
achievements
??
[];
achievements
.
assignAll
(
data
?
.
achievements
??
[]
)
;
},
showAppNavigatorDialog:
true
,
onFailure:
(
msg
,
_
,
__
)
async
{
achievements
.
clear
();
},
showAppNavigatorDialog:
false
,
);
}
}
\ No newline at end of file
lib/screen/affiliate/affiliate_tab_viewmodel.dart
View file @
89983084
...
...
@@ -13,7 +13,7 @@ class AffiliateTabViewModel extends RestfulApiViewModel {
final
RxList
<
AffiliateCategoryModel
>
allAffiliateCategories
=
<
AffiliateCategoryModel
>[].
obs
;
final
RxList
<
AffiliateProductTopSaleModel
>
affiliateProducts
=
<
AffiliateProductTopSaleModel
>[].
obs
;
final
RxBool
isLoading
=
false
.
obs
;
var
overview
=
Rxn
<
CashbackOverviewModel
>();
final
Rxn
<
CashbackOverviewModel
>
overview
=
Rxn
<
CashbackOverviewModel
>();
void
Function
((
List
<
AffiliateBrandModel
>,
String
)
data
)?
onShowAffiliateBrandPopup
;
@override
...
...
@@ -34,62 +34,79 @@ class AffiliateTabViewModel extends RestfulApiViewModel {
}
Future
<
void
>
_getAffiliateBrandGetList
()
async
{
try
{
final
result
=
await
client
.
affiliateBrandGetList
();
affiliateBrands
.
value
=
result
.
data
??
[];
}
catch
(
error
)
{
print
(
"Error fetching affiliate brands:
$error
"
);
}
await
callApi
<
List
<
AffiliateBrandModel
>>(
request:
()
=>
client
.
affiliateBrandGetList
(),
onSuccess:
(
data
,
_
)
{
affiliateBrands
.
assignAll
(
data
);
},
onFailure:
(
msg
,
_
,
__
)
async
{
affiliateBrands
.
clear
();
},
showAppNavigatorDialog:
true
,
);
}
Future
<
void
>
_getAffiliateCategoryGetList
()
async
{
try
{
final
result
=
await
client
.
affiliateCategoryGetList
();
final
category
=
AffiliateCategoryModel
(
code:
AffiliateCategoryType
.
other
,
name:
"Khác"
,
);
final
results
=
(
result
.
data
??
[]);
allAffiliateCategories
.
value
=
results
;
await
callApi
<
List
<
AffiliateCategoryModel
>>(
request:
()
=>
client
.
affiliateCategoryGetList
(),
onSuccess:
(
data
,
_
)
{
final
category
=
AffiliateCategoryModel
(
code:
AffiliateCategoryType
.
other
,
name:
"Khác"
,
);
final
results
=
data
;
allAffiliateCategories
.
assignAll
(
results
);
final
data
=
results
.
take
(
7
).
toList
();
data
.
add
(
category
);
affiliateCategories
.
value
=
data
;
}
catch
(
error
)
{
print
(
"Error fetching affiliate brands:
$error
"
);
}
final
limitedData
=
results
.
take
(
7
).
toList
();
limitedData
.
add
(
category
);
affiliateCategories
.
assignAll
(
limitedData
);
},
onFailure:
(
msg
,
_
,
__
)
async
{
affiliateCategories
.
clear
();
allAffiliateCategories
.
clear
();
},
showAppNavigatorDialog:
true
,
);
}
Future
<
void
>
_getAffiliateProductTopSale
()
async
{
try
{
final
result
=
await
client
.
affiliateProductTopSale
();
affiliateProducts
.
value
=
result
.
data
??
[];
}
catch
(
error
)
{
print
(
"Error fetching affiliate brands:
$error
"
);
}
await
callApi
<
List
<
AffiliateProductTopSaleModel
>>(
request:
()
=>
client
.
affiliateProductTopSale
(),
onSuccess:
(
data
,
_
)
{
affiliateProducts
.
assignAll
(
data
);
},
onFailure:
(
msg
,
_
,
__
)
async
{
affiliateProducts
.
clear
();
},
showAppNavigatorDialog:
true
,
);
}
Future
<
void
>
_getAffiliateOverview
()
async
{
try
{
final
result
=
await
client
.
getCashBackOverview
();
overview
.
value
=
result
.
data
;
}
catch
(
error
)
{
print
(
"Error fetching affiliate brands:
$error
"
);
}
await
callApi
<
CashbackOverviewModel
>(
request:
()
=>
client
.
getCashBackOverview
(),
onSuccess:
(
data
,
_
)
{
overview
.
value
=
data
;
},
onFailure:
(
msg
,
_
,
__
)
async
{
overview
.
value
=
null
;
},
showAppNavigatorDialog:
true
,
);
}
affiliateBrandGetListBuyCategory
(
AffiliateCategoryModel
category
)
async
{
showLoading
();
try
{
final
result
=
await
client
.
affiliateBrandGetList
(
categoryCode:
AffiliateCategoryModel
.
codeToJson
(
category
.
code
));
hideLoading
();
final
data
=
result
.
data
??
[]
;
if
(
result
.
isSuccess
&&
data
.
isNotEmpty
)
{
onShowAffiliateBrandPopup
?.
call
((
data
,
category
.
name
??
''
));
}
}
catch
(
error
)
{
hideLoading
();
print
(
"Error fetching affiliate brands:
$error
"
);
}
Future
<
void
>
affiliateBrandGetListBuyCategory
(
AffiliateCategoryModel
category
)
async
{
await
callApi
<
List
<
AffiliateBrandModel
>>(
request:
()
=>
client
.
affiliateBrandGetList
(
categoryCode:
AffiliateCategoryModel
.
codeToJson
(
category
.
code
)),
onSuccess:
(
data
,
_
)
{
if
(
data
.
isNotEmpty
)
{
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/daily_checkin/daily_checkin_viewmodel.dart
View file @
89983084
import
'package:get/get_rx/src/rx_types/rx_types.dart'
;
import
'package:mypoint_flutter_app/networking/restful_api_client_all_request.dart'
;
import
'../../configs/constants.dart'
;
import
'../../networking/restful_api_viewmodel.dart'
;
import
'daily_checkin_models.dart'
;
class
DailyCheckInViewModel
extends
RestfulApiViewModel
{
var
checkInData
=
Rxn
<
CheckInDataModel
>();
var
submitData
=
Rxn
<
SubmitCheckInData
>();
final
Rxn
<
CheckInDataModel
>
checkInData
=
Rxn
<
CheckInDataModel
>();
final
Rxn
<
SubmitCheckInData
>
submitData
=
Rxn
<
SubmitCheckInData
>();
void
Function
(
String
message
,
bool
onBack
)?
onShowAlertError
;
void
Function
(
SubmitCheckInData
?
data
)?
submitDataResponse
;
...
...
@@ -17,40 +16,34 @@ class DailyCheckInViewModel extends RestfulApiViewModel {
}
@override
onInit
()
{
void
onInit
()
{
super
.
onInit
();
_rewardOpportunityGetList
();
}
Future
<
void
>
_rewardOpportunityGetList
()
async
{
showLoading
();
try
{
final
response
=
await
client
.
rewardOpportunityGetList
();
hideLoading
();
checkInData
.
value
=
response
.
data
;
if
(!
response
.
isSuccess
)
{
onShowAlertError
?.
call
(
response
.
errorMessage
??
Constants
.
commonError
,
true
);
}
}
catch
(
error
)
{
hideLoading
();
onShowAlertError
?.
call
(
Constants
.
commonError
,
true
);
}
await
callApi
<
CheckInDataModel
>(
request:
()
=>
client
.
rewardOpportunityGetList
(),
onSuccess:
(
data
,
_
)
{
checkInData
.
value
=
data
;
},
onFailure:
(
msg
,
_
,
__
)
async
{
onShowAlertError
?.
call
(
msg
,
true
);
},
);
}
Future
<
void
>
submitCheckIn
()
async
{
showLoading
();
try
{
final
response
=
await
client
.
submitCheckIn
();
hideLoading
();
submitData
.
value
=
response
.
data
;
submitDataResponse
?.
call
(
response
.
data
);
_rewardOpportunityGetList
();
if
(!
response
.
isSuccess
)
{
onShowAlertError
?.
call
(
response
.
errorMessage
??
Constants
.
commonError
,
false
);
}
}
catch
(
error
)
{
hideLoading
();
onShowAlertError
?.
call
(
Constants
.
commonError
,
false
);
}
await
callApi
<
SubmitCheckInData
>(
request:
()
=>
client
.
submitCheckIn
(),
onSuccess:
(
data
,
_
)
{
submitData
.
value
=
data
;
submitDataResponse
?.
call
(
data
);
_rewardOpportunityGetList
();
// Refresh data after successful check-in
},
onFailure:
(
msg
,
_
,
__
)
async
{
onShowAlertError
?.
call
(
msg
,
false
);
},
);
}
}
\ No newline at end of file
lib/screen/game/game_cards/game_card_viewmodel.dart
View file @
89983084
...
...
@@ -6,32 +6,38 @@ import '../../../widgets/alert/popup_data_model.dart';
import
'../models/game_bundle_item_model.dart'
;
class
GameCardViewModel
extends
RestfulApiViewModel
{
var
data
=
Rxn
<
GameBundleItemModel
>();
final
Rxn
<
GameBundleItemModel
>
data
=
Rxn
<
GameBundleItemModel
>();
void
Function
(
String
message
,
bool
onClose
)?
onShowAlertError
;
void
Function
(
PopupDataModel
popup
)?
submitGameCardSuccess
;
void
Function
()?
getGameDetailSuccess
;
Future
<
void
>
submitGameCard
(
String
gameId
,
int
itemId
)
async
{
showProgressIndicator
();
final
response
=
await
client
.
submitGameCard
(
gameId
,
itemId
.
toString
());
hideProgressIndicator
();
final
popupData
=
response
.
data
?.
popup
;
if
(
response
.
isSuccess
&&
popupData
!=
null
)
{
submitGameCardSuccess
?.
call
(
popupData
);
}
else
{
onShowAlertError
?.
call
(
response
.
errorMessage
??
Constants
.
commonError
,
false
);
}
await
callApi
<
GameBundleItemModel
>(
request:
()
=>
client
.
submitGameCard
(
gameId
,
itemId
.
toString
()),
onSuccess:
(
data
,
_
)
{
final
popupData
=
data
?.
popup
;
if
(
popupData
!=
null
)
{
submitGameCardSuccess
?.
call
(
popupData
);
}
else
{
onShowAlertError
?.
call
(
Constants
.
commonError
,
false
);
}
},
onFailure:
(
msg
,
_
,
__
)
async
{
onShowAlertError
?.
call
(
msg
,
false
);
},
);
}
Future
<
void
>
getGameDetail
({
String
?
id
})
async
{
showLoading
();
final
response
=
await
client
.
getGameDetail
(
id
??
data
.
value
?.
id
??
''
);
hideLoading
();
if
(
response
.
data
!=
null
)
{
data
.
value
=
response
.
data
;
getGameDetailSuccess
?.
call
();
}
else
{
onShowAlertError
?.
call
(
response
.
errorMessage
??
Constants
.
commonError
,
true
);
}
await
callApi
<
GameBundleItemModel
>(
request:
()
=>
client
.
getGameDetail
(
id
??
data
.
value
?.
id
??
''
),
onSuccess:
(
data
,
_
)
{
this
.
data
.
value
=
data
;
getGameDetailSuccess
?.
call
();
},
onFailure:
(
msg
,
_
,
__
)
async
{
onShowAlertError
?.
call
(
msg
,
true
);
},
);
}
}
\ No newline at end of file
lib/screen/health_book/health_book_card_detail_viewmodel.dart
View file @
89983084
...
...
@@ -9,9 +9,9 @@ class HealthBookCardDetailViewModel extends RestfulApiViewModel {
void
Function
(
String
message
)?
onShowAlertError
;
Future
<
void
>
getHealthBookCardDetail
(
String
cardId
)
async
{
show
ProgressIndicator
();
show
Loading
();
final
response
=
await
client
.
getDetailHealthBookCard
(
cardId
);
showProgressIndicator
();
hideLoading
();
if
(
response
.
isSuccess
)
{
card
.
value
=
response
.
data
;
}
else
{
...
...
lib/screen/history_point/history_point_viewmodel.dart
View file @
89983084
...
...
@@ -5,32 +5,27 @@ import 'models/history_point_models.dart';
import
'models/transaction_summary_by_date_model.dart'
;
class
HistoryPointViewModel
extends
RestfulApiViewModel
{
var
historyPoint
=
Rxn
<
ListHistoryResponseModel
>();
var
transactionSummary
=
Rxn
<
TransactionSummaryByDateModel
>();
final
Rxn
<
ListHistoryResponseModel
>
historyPoint
=
Rxn
<
ListHistoryResponseModel
>();
final
Rxn
<
TransactionSummaryByDateModel
>
transactionSummary
=
Rxn
<
TransactionSummaryByDateModel
>();
final
RxInt
selectedTabIndex
=
0
.
obs
;
DateTime
selectedDate
=
DateTime
.
now
();
@override
onInit
()
{
void
onInit
()
{
super
.
onInit
();
freshData
();
}
changeDate
(
bool
prevMonth
)
{
void
changeDate
(
bool
prevMonth
)
{
selectedDate
=
DateTime
(
selectedDate
.
year
,
selectedDate
.
month
+
(
prevMonth
?
-
1
:
1
),
1
);
freshData
();
}
Future
<
void
>
freshData
()
async
{
showLoading
();
try
{
await
Future
.
wait
<
void
>([
_getTransactionGetSummaryByDate
(),
_getTransactionSummaryByDateModel
(),
],
eagerError:
false
);
}
finally
{
hideLoading
();
}
await
Future
.
wait
<
void
>([
_getTransactionGetSummaryByDate
(),
_getTransactionSummaryByDateModel
(),
],
eagerError:
false
);
}
Future
<
void
>
_getTransactionGetSummaryByDate
()
async
{
...
...
@@ -39,8 +34,16 @@ class HistoryPointViewModel extends RestfulApiViewModel {
'year'
:
selectedDate
.
year
,
'lang'
:
'vi'
,
};
final
res
=
await
client
.
transactionGetSummaryByDate
(
body
);
transactionSummary
.
value
=
res
.
data
;
await
callApi
<
TransactionSummaryByDateModel
>(
request:
()
=>
client
.
transactionGetSummaryByDate
(
body
),
onSuccess:
(
data
,
_
)
{
transactionSummary
.
value
=
data
;
},
onFailure:
(
msg
,
_
,
__
)
async
{
transactionSummary
.
value
=
null
;
},
);
}
Future
<
void
>
_getTransactionSummaryByDateModel
()
async
{
...
...
@@ -53,7 +56,15 @@ class HistoryPointViewModel extends RestfulApiViewModel {
'start'
:
0
,
'lang'
:
'vi'
,
};
final
res
=
await
client
.
transactionHistoryGetList
(
body
);
historyPoint
.
value
=
res
.
data
;
await
callApi
<
ListHistoryResponseModel
>(
request:
()
=>
client
.
transactionHistoryGetList
(
body
),
onSuccess:
(
data
,
_
)
{
historyPoint
.
value
=
data
;
},
onFailure:
(
msg
,
_
,
__
)
async
{
historyPoint
.
value
=
null
;
},
);
}
}
\ No newline at end of file
lib/screen/interested_categories/interestied_categories_viewmodel.dart
View file @
89983084
import
'package:get/get_rx/src/rx_types/rx_types.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
'../../configs/constants.dart'
;
import
'models/interested_categories_model.dart'
;
class
InterestedCategoriesViewModel
extends
RestfulApiViewModel
{
var
interestedCategories
=
Rxn
<
InterestedCategoriesResponse
>();
final
Rxn
<
InterestedCategoriesResponse
>
interestedCategories
=
Rxn
<
InterestedCategoriesResponse
>();
Set
<
String
>
selectedIds
=
{};
void
Function
(
String
message
)?
onShowAlertError
;
Future
<
void
>
getInterestedCategories
()
async
{
showLoading
();
try
{
final
response
=
await
client
.
categoryTopLevelGetList
();
hideLoading
();
if
(
response
.
isSuccess
&&
response
.
data
!=
null
)
{
final
categories
=
response
.
data
!;
await
callApi
<
InterestedCategoriesResponse
>(
request:
()
=>
client
.
categoryTopLevelGetList
(),
onSuccess:
(
data
,
_
)
{
selectedIds
=
c
at
egories
.
listItems
d
at
a
.
listItems
?.
where
((
item
)
=>
item
.
subscribed
==
"1"
)
.
map
((
item
)
=>
item
.
categoryCode
??
''
)
.
where
((
code
)
=>
code
.
isNotEmpty
)
.
toList
()
.
toSet
()
??
<
String
>{};
interestedCategories
.
value
=
categories
;
}
else
{
onShowAlertError
?.
call
(
response
.
message
??
Constants
.
commonError
);
}
}
catch
(
error
)
{
hideLoading
();
onShowAlertError
?.
call
(
Constants
.
commonError
);
}
interestedCategories
.
value
=
data
;
},
onFailure:
(
msg
,
_
,
_
)
async
{
onShowAlertError
?.
call
(
msg
);
},
);
}
submitInterestedCategories
()
async
{
Future
<
void
>
submitInterestedCategories
()
async
{
final
categories
=
selectedIds
.
toList
();
showLoading
();
try
{
final
response
=
await
client
.
submitCategorySubscribe
(
categories
.
join
(
','
));
hideLoading
();
onShowAlertError
?.
call
(
response
.
isSuccess
?
"Cập nhật sở thích thành công"
:
response
.
message
??
Constants
.
commonError
,
);
final
List
<
String
>
categoryCodes
=
interestedCategories
.
value
?.
listItems
?.
map
((
item
)
=>
item
.
categoryCode
??
''
)
.
where
((
code
)
=>
code
.
isNotEmpty
)
.
toList
()
??
[];
final
filteredList
=
categoryCodes
?.
where
((
item
)
=>
!
categories
.
contains
(
item
)).
toList
();
if
(
filteredList
==
null
||
filteredList
.
isEmpty
)
return
;
submitUnsubscribeInterestedCategories
(
filteredList
!);
}
catch
(
error
)
{
hideLoading
();
onShowAlertError
?.
call
(
Constants
.
commonError
);
await
callApi
<
EmptyCodable
>(
request:
()
=>
client
.
submitCategorySubscribe
(
categories
.
join
(
','
)),
onSuccess:
(
data
,
_
)
{
onShowAlertError
?.
call
(
"Cập nhật sở thích thành công"
);
_handleUnsubscribeCategories
(
categories
);
},
onFailure:
(
msg
,
_
,
_
)
async
{
onShowAlertError
?.
call
(
msg
);
},
);
}
void
_handleUnsubscribeCategories
(
List
<
String
>
categories
)
{
final
List
<
String
>
categoryCodes
=
interestedCategories
.
value
?.
listItems
?.
map
((
item
)
=>
item
.
categoryCode
??
''
)
.
where
((
code
)
=>
code
.
isNotEmpty
)
.
toList
()
??
[];
final
filteredList
=
categoryCodes
.
where
((
item
)
=>
!
categories
.
contains
(
item
)).
toList
();
if
(
filteredList
.
isNotEmpty
)
{
submitUnsubscribeInterestedCategories
(
filteredList
);
}
}
submitUnsubscribeInterestedCategories
(
List
<
String
>
categories
)
async
{
final
_
=
await
client
.
submitCategoryUnsubscribeList
(
categories
.
join
(
','
));
Future
<
void
>
submitUnsubscribeInterestedCategories
(
List
<
String
>
categories
)
async
{
await
callApi
<
EmptyCodable
>(
request:
()
=>
client
.
submitCategoryUnsubscribeList
(
categories
.
join
(
','
)),
onSuccess:
(
data
,
_
)
{
// Silent success for unsubscribe
},
onFailure:
(
msg
,
_
,
_
)
async
{
// Silent failure for unsubscribe
},
);
}
}
lib/screen/invite_friend_campaign/invite_friend_campaign_viewmodel.dart
View file @
89983084
...
...
@@ -5,53 +5,55 @@ import '../../networking/restful_api_viewmodel.dart';
import
'models/invite_friend_campaign_model.dart'
;
class
InviteFriendCampaignViewModel
extends
RestfulApiViewModel
{
var
inviteFriendDetail
=
Rxn
<
InviteFriendDetailModel
>();
var
campaignDetail
=
Rxn
<
CampaignInviteFriendDetail
>();
final
Rxn
<
InviteFriendDetailModel
>
inviteFriendDetail
=
Rxn
<
InviteFriendDetailModel
>();
final
Rxn
<
CampaignInviteFriendDetail
>
campaignDetail
=
Rxn
<
CampaignInviteFriendDetail
>();
void
Function
(
String
message
,
bool
onBack
)?
onShowAlertError
;
void
Function
(
String
,
String
)?
phoneInviteFriendResponse
;
loadData
()
{
void
loadData
()
{
_getInviteFriendDetail
();
_getCampaignInviteFriendDetail
();
}
Future
<
void
>
phoneInviteFriend
(
String
phone
)
async
{
showLoading
();
try
{
final
response
=
await
client
.
phoneInviteFriend
(
phone
);
hideLoading
()
;
final
sms
=
response
.
data
?.
sms
??
''
;
if
(
response
.
isSuccess
&&
sms
.
isNotEmpty
)
{
phoneInviteFriendResponse
?.
call
(
sms
,
phone
);
}
e
lse
{
onShowAlertError
?.
call
(
response
.
errorMessage
??
Constants
.
commonError
,
false
);
}
}
catch
(
error
)
{
hideLoading
(
);
onShowAlertError
?.
call
(
Constants
.
commonError
,
false
);
}
await
callApi
<
InviteFriendResponse
>(
request:
()
=>
client
.
phoneInviteFriend
(
phone
),
onSuccess:
(
data
,
_
)
{
final
sms
=
data
?.
sms
??
''
;
if
(
sms
.
isNotEmpty
)
{
phoneInviteFriendResponse
?.
call
(
sms
,
phone
);
}
else
{
onShowAlertError
?.
call
(
Constants
.
commonError
,
fa
lse
);
}
}
,
onFailure:
(
msg
,
_
,
__
)
async
{
onShowAlertError
?.
call
(
msg
,
false
);
},
);
}
Future
<
void
>
_getInviteFriendDetail
()
async
{
showLoading
();
try
{
final
response
=
await
client
.
getCampaignInviteFriend
();
hideLoading
();
inviteFriendDetail
.
value
=
response
.
data
;
if
(!
response
.
isSuccess
)
{
onShowAlertError
?.
call
(
response
.
errorMessage
??
Constants
.
commonError
,
true
);
}
}
catch
(
error
)
{
onShowAlertError
?.
call
(
Constants
.
commonError
,
true
);
}
finally
{
hideLoading
();
}
Future
<
void
>
_getInviteFriendDetail
()
async
{
await
callApi
<
InviteFriendDetailModel
>(
request:
()
=>
client
.
getCampaignInviteFriend
(),
onSuccess:
(
data
,
_
)
{
inviteFriendDetail
.
value
=
data
;
},
onFailure:
(
msg
,
_
,
__
)
async
{
onShowAlertError
?.
call
(
msg
,
true
);
},
);
}
Future
<
void
>
_getCampaignInviteFriendDetail
()
async
{
try
{
final
response
=
await
client
.
getDetailCampaignInviteFriend
();
campaignDetail
.
value
=
response
.
data
;
}
catch
(
_
)
{}
await
callApi
<
CampaignInviteFriendDetail
>(
request:
()
=>
client
.
getDetailCampaignInviteFriend
(),
onSuccess:
(
data
,
_
)
{
campaignDetail
.
value
=
data
;
},
onFailure:
(
msg
,
_
,
__
)
async
{
// Silent failure for this optional call
},
showAppNavigatorDialog:
false
,
);
}
}
lib/screen/pipi/pipi_detail_viewmodel.dart
View file @
89983084
...
...
@@ -4,9 +4,7 @@ import '../../networking/restful_api_viewmodel.dart';
import
'../home/models/pipi_detail_model.dart'
;
class
PipiDetailViewModel
extends
RestfulApiViewModel
{
var
items
=
RxList
<
PipiSupportItemModel
>();
PipiDetailViewModel
();
final
RxList
<
PipiSupportItemModel
>
items
=
<
PipiSupportItemModel
>[].
obs
;
@override
void
onInit
()
{
...
...
@@ -15,11 +13,14 @@ class PipiDetailViewModel extends RestfulApiViewModel {
}
Future
<
void
>
fetchPipiDetails
()
async
{
try
{
final
response
=
await
client
.
getPipiDetail
();
items
.
value
=
response
.
data
?.
items
??
[];
}
catch
(
error
)
{
print
(
"Error fetching Pipi details:
$error
"
);
}
await
callApi
<
PipiDetailResponseModel
>(
request:
()
=>
client
.
getPipiDetail
(),
onSuccess:
(
data
,
_
)
{
items
.
assignAll
(
data
?.
items
??
[]);
},
onFailure:
(
msg
,
_
,
__
)
async
{
items
.
clear
();
},
);
}
}
\ No newline at end of file
lib/screen/register_campaign/register_form_input_screen.dart
View file @
89983084
...
...
@@ -208,8 +208,7 @@ class _RegisterFormInputScreenState extends BaseState<RegisterFormInputScreen> w
}
void
_continueToPaymentHandle
()
{
final
verifyURL
=
_viewModel
.
form
.
value
?.
verify
?.
url
??
''
;
if
(
verifyURL
.
isNotEmpty
)
{
if
(
_viewModel
.
verifyUrl
.
isNotEmpty
)
{
_viewModel
.
verifyRegisterForm
();
}
else
{
_gotoPaymentScreen
();
...
...
lib/screen/register_campaign/register_form_input_viewmodel.dart
View file @
89983084
...
...
@@ -12,6 +12,9 @@ class RegisterFormInputViewModel extends RestfulApiViewModel {
void
Function
(
String
message
)?
onShowAlertError
;
void
Function
(
VerifyRegisterCampaignModel
data
)?
verifyRegisterFormSuccess
;
String
get
verifyUrl
{
return
form
.
value
?.
verify
?.
url
??
''
;
}
Future
<
void
>
fetchRegisterFormInput
(
String
id
)
async
{
final
response
=
await
client
.
getRegistrationForm
(
id
);
form
.
value
=
response
.
data
;
...
...
@@ -21,11 +24,10 @@ class RegisterFormInputViewModel extends RestfulApiViewModel {
}
Future
<
void
>
verifyRegisterForm
()
async
{
showProgressIndicator
();
final
path
=
form
.
value
?.
formRegistration
?.
verify
?.
url
??
'/accountPasswordReset/1.0.0'
;
showLoading
();
final
metaData
=
(
form
.
value
?.
submitParams
??
{}).
toJsonString
();
final
response
=
await
client
.
verifyRegisterForm
(
path
,
{
'metadata'
:
metaData
});
hide
ProgressIndicator
();
final
response
=
await
client
.
verifyRegisterForm
(
verifyUrl
,
{
'metadata'
:
metaData
});
hide
Loading
();
final
data
=
response
.
data
;
if
(!
response
.
isSuccess
&&
data
!=
null
)
{
onShowAlertError
?.
call
(
response
.
errorMessage
??
Constants
.
commonError
);
...
...
lib/screen/transaction/transaction_detail_screen.dart
View file @
89983084
...
...
@@ -49,13 +49,13 @@ class _TransactionDetailScreenState extends BaseState<TransactionDetailScreen> w
_viewModel
=
Get
.
put
(
TransactionDetailViewModel
(
product:
_product
!,
quantity:
_quantity
,
targetPhoneNumber:
_targetPhoneNumber
,
metaData:
_metaData
),
);
_viewModel
.
refreshData
();
_viewModel
.
onShowAlertError
=
(
message
)
{
if
(
message
.
isNotEmpty
)
{
if
(
message
.
isEmpty
)
return
;
WidgetsBinding
.
instance
.
addPostFrameCallback
((
_
)
{
showAlertError
(
content:
message
);
}
}
);
};
_viewModel
.
refreshData
();
}
@override
...
...
lib/screen/transaction/transaction_detail_viewmodel.dart
View file @
89983084
...
...
@@ -39,12 +39,6 @@ class TransactionDetailViewModel extends RestfulApiViewModel {
TransactionDetailViewModel
({
required
this
.
product
,
required
this
.
quantity
,
this
.
targetPhoneNumber
,
this
.
metaData
});
@override
void
onInit
()
{
super
.
onInit
();
refreshData
();
}
Future
<
void
>
refreshData
()
async
{
isLoading
.
value
=
true
;
await
Future
.
wait
([
_getPreviewOrderPayment
(),
_getPaymentMethods
(),
_getPaymentBankAccounts
()]);
...
...
lib/screen/voucher/mobile_card/my_mobile_card_detail_viewmodel.dart
View file @
89983084
...
...
@@ -43,7 +43,7 @@ class MyMobileCardDetailViewModel extends RestfulApiViewModel {
Future
<
void
>
onChangeCardStatus
()
async
{
final
newState
=
!
isUsed
.
value
;
show
ProgressIndicator
();
show
Loading
();
try
{
final
response
=
newState
?
await
client
.
myProductMarkAsUsed
(
itemId
)
:
await
client
.
myProductMarkAsNotUsedYet
(
itemId
);
if
(
response
.
isSuccess
)
{
...
...
@@ -52,7 +52,7 @@ class MyMobileCardDetailViewModel extends RestfulApiViewModel {
}
catch
(
_
)
{
}
finally
{
hide
ProgressIndicator
();
hide
Loading
();
}
}
}
\ No newline at end of file
lib/screen/voucher/voucher_code_card_screen.dart
View file @
89983084
...
...
@@ -2,6 +2,7 @@ import 'package:barcode_widget/barcode_widget.dart';
import
'package:flutter/material.dart'
;
import
'package:flutter/services.dart'
;
import
'package:mypoint_flutter_app/widgets/back_button.dart'
;
import
'package:mypoint_flutter_app/widgets/custom_toast_message.dart'
;
import
'package:mypoint_flutter_app/widgets/dashed_line.dart'
;
import
'package:qr_flutter/qr_flutter.dart'
;
import
'../../resources/base_color.dart'
;
...
...
@@ -80,7 +81,7 @@ class VoucherCodeCardScreen extends StatelessWidget {
GestureDetector
(
onTap:
()
{
Clipboard
.
setData
(
ClipboardData
(
text:
code
));
ScaffoldMessenger
.
of
(
context
).
showSnackBar
(
const
SnackBar
(
content:
Text
(
'Đã sao chép mã'
)
))
;
showToastMessage
(
'Đã sao chép mã'
);
},
child:
Container
(
padding:
const
EdgeInsets
.
symmetric
(
horizontal:
12
,
vertical:
4
),
...
...
lib/screen/voucher/voucher_list/voucher_list_viewmodel.dart
View file @
89983084
...
...
@@ -133,9 +133,9 @@ class VoucherListViewModel extends RestfulApiViewModel {
}
void
submitCampaignViewVoucherComplete
()
async
{
show
ProgressIndicator
();
final
response
=
await
client
.
submitCampaignViewVoucherComplete
();
hide
ProgressIndicator
();
submitCampaignViewVoucherResponse
?.
call
(
response
);
show
Loading
();
final
response
=
await
client
.
submitCampaignViewVoucherComplete
();
hide
Loading
();
submitCampaignViewVoucherResponse
?.
call
(
response
);
}
}
Prev
1
2
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