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
fa01087d
Commit
fa01087d
authored
Jul 04, 2025
by
DatHV
Browse files
update brand, detail..
parent
c8abf95b
Changes
108
Hide whitespace changes
Inline
Side-by-side
lib/configs/api_paths.dart
View file @
fa01087d
...
@@ -63,4 +63,15 @@ class APIPaths {
...
@@ -63,4 +63,15 @@ class APIPaths {
static
const
String
locationDistrictGetList
=
"/locationDistrictGetList/1.0.0"
;
static
const
String
locationDistrictGetList
=
"/locationDistrictGetList/1.0.0"
;
static
const
String
locationProvinceGetList
=
"/locationProvinceGetList/1.0.0"
;
static
const
String
locationProvinceGetList
=
"/locationProvinceGetList/1.0.0"
;
static
const
String
getMembershipLevelInfo
=
"/primaryMembershipLevelGetList/2.0.0"
;
static
const
String
getMembershipLevelInfo
=
"/primaryMembershipLevelGetList/2.0.0"
;
static
const
String
getTopUpBrands
=
"/product/api/v2.0/topup-brands"
;
static
const
String
checkMobileNetwork
=
"/order/api/v1.0/check-mobile-network/"
;
static
const
String
productMobileCardGetList
=
"/productMobileCardGetList/1.0.0"
;
static
const
String
redeemMobileCard
=
"/productMobileCardRedeemRequest/1.0.0"
;
static
const
String
getMobileCardCode
=
"/myProductItemGetDetail/1.0.0"
;
static
const
String
productTopUpsBrands
=
"/product/api/v2.0/topups/brands"
;
static
const
String
getNetworkProducts
=
"/product/api/v2.0/topups"
;
static
const
String
redeemProductTopUps
=
"/product/api/v2.0/topups/redeem"
;
static
const
String
historyCashBackPoint
=
"/cashback/orders"
;
static
const
String
historyCashBackPointDetail
=
"/cashback/order/details"
;
static
const
String
affiliateBrandGetDetail
=
"/affiliateBrandGetDetail/1.0.0"
;
}
}
\ No newline at end of file
lib/directional/directional_action_type.dart
View file @
fa01087d
...
@@ -43,7 +43,7 @@ enum DirectionalScreenName {
...
@@ -43,7 +43,7 @@ enum DirectionalScreenName {
memberShip
,
memberShip
,
ranking
,
ranking
,
mobileTopup
,
mobileTopup
,
mobileTopupData
,
carrierPackage
,
topup
,
topup
,
register
,
register
,
gifts
,
gifts
,
...
@@ -208,7 +208,7 @@ extension DirectionalScreenNameExtension on DirectionalScreenName {
...
@@ -208,7 +208,7 @@ extension DirectionalScreenNameExtension on DirectionalScreenName {
return
"APP_SCREEN_RANKING_PROGRAM"
;
return
"APP_SCREEN_RANKING_PROGRAM"
;
case
DirectionalScreenName
.
mobileTopup
:
case
DirectionalScreenName
.
mobileTopup
:
return
"APP_SCREEN_PRODUCT_MOBILE_TOPUP"
;
return
"APP_SCREEN_PRODUCT_MOBILE_TOPUP"
;
case
DirectionalScreenName
.
mobileTopupData
:
case
DirectionalScreenName
.
carrierPackage
:
return
"APP_SCREEN_MOBILE_TOPUP_DATA"
;
return
"APP_SCREEN_MOBILE_TOPUP_DATA"
;
case
DirectionalScreenName
.
topup
:
case
DirectionalScreenName
.
topup
:
return
"APP_SCREEN_TOPUP"
;
return
"APP_SCREEN_TOPUP"
;
...
@@ -319,7 +319,7 @@ extension DirectionalScreenNameExtension on DirectionalScreenName {
...
@@ -319,7 +319,7 @@ extension DirectionalScreenNameExtension on DirectionalScreenName {
static
DirectionalScreenName
fromRawValue
(
String
rawValue
)
{
static
DirectionalScreenName
fromRawValue
(
String
rawValue
)
{
return
DirectionalScreenName
.
values
.
firstWhere
(
return
DirectionalScreenName
.
values
.
firstWhere
(
(
e
)
=>
e
.
rawValue
==
rawValue
,
(
e
)
=>
e
.
rawValue
==
rawValue
.
trim
()
,
orElse:
()
=>
DirectionalScreenName
.
unknown
,
orElse:
()
=>
DirectionalScreenName
.
unknown
,
);
);
}
}
...
...
lib/directional/directional_screen.dart
View file @
fa01087d
import
'package:flutter/cupertino.dart'
;
import
'package:flutter/cupertino.dart'
;
import
'package:get/get.dart'
;
import
'package:get/get.dart'
;
import
'package:mypoint_flutter_app/extensions/string_extension.dart'
;
import
'package:mypoint_flutter_app/preference/data_preference.dart'
;
import
'package:url_launcher/url_launcher.dart'
;
import
'package:uuid/uuid.dart'
;
import
'../screen/webview/web_view_screen.dart'
;
import
'../screen/webview/web_view_screen.dart'
;
import
'../shared/router_gage.dart'
;
import
'../shared/router_gage.dart'
;
import
'directional_action_type.dart'
;
import
'directional_action_type.dart'
;
...
@@ -18,6 +22,13 @@ class DirectionalScreen {
...
@@ -18,6 +22,13 @@ class DirectionalScreen {
return
DirectionalScreen
.
_
(
clickActionType:
clickActionType
,
clickActionParam:
clickActionParam
);
return
DirectionalScreen
.
_
(
clickActionType:
clickActionType
,
clickActionParam:
clickActionParam
);
}
}
static
DirectionalScreen
?
buildByName
({
required
DirectionalScreenName
name
,
String
?
clickActionParam
})
{
if
(
name
==
DirectionalScreenName
.
appScreen
)
{
return
DirectionalScreen
.
_
(
clickActionType:
clickActionParam
,
clickActionParam:
null
);
}
return
DirectionalScreen
.
_
(
clickActionType:
name
.
rawValue
,
clickActionParam:
clickActionParam
);
}
factory
DirectionalScreen
.
fromJson
(
Map
<
String
,
dynamic
>
json
)
=>
DirectionalScreen
.
_
(
factory
DirectionalScreen
.
fromJson
(
Map
<
String
,
dynamic
>
json
)
=>
DirectionalScreen
.
_
(
clickActionType:
json
[
'click_action_type'
]
as
String
?,
clickActionType:
json
[
'click_action_type'
]
as
String
?,
clickActionParam:
json
[
'click_action_param'
]
as
String
?,
clickActionParam:
json
[
'click_action_param'
]
as
String
?,
...
@@ -59,7 +70,7 @@ class DirectionalScreen {
...
@@ -59,7 +70,7 @@ class DirectionalScreen {
case
DirectionalScreenName
.
gifts
:
case
DirectionalScreenName
.
gifts
:
Get
.
toNamed
(
achievementListScreen
);
Get
.
toNamed
(
achievementListScreen
);
return
true
;
return
true
;
case
DirectionalScreenName
.
pointHunting
:
case
DirectionalScreenName
.
pointHunting
||
DirectionalScreenName
.
achievement
:
Get
.
toNamed
(
achievementListScreen
,
arguments:
true
);
Get
.
toNamed
(
achievementListScreen
,
arguments:
true
);
return
true
;
return
true
;
case
DirectionalScreenName
.
myPurchaseItems
||
DirectionalScreenName
.
myPurchaseItemsWaitingList
:
case
DirectionalScreenName
.
myPurchaseItems
||
DirectionalScreenName
.
myPurchaseItemsWaitingList
:
...
@@ -68,9 +79,86 @@ class DirectionalScreen {
...
@@ -68,9 +79,86 @@ class DirectionalScreen {
case
DirectionalScreenName
.
orderMenu
:
case
DirectionalScreenName
.
orderMenu
:
Get
.
toNamed
(
orderMenuScreen
);
Get
.
toNamed
(
orderMenuScreen
);
return
true
;
return
true
;
case
DirectionalScreenName
.
topup
||
DirectionalScreenName
.
mobileTopup
:
Get
.
toNamed
(
phoneTopUpScreen
);
return
true
;
case
DirectionalScreenName
.
carrierPackage
:
BaseWebViewInput
input
=
BaseWebViewInput
(
url:
clickActionParam
??
""
);
Get
.
toNamed
(
baseWebViewScreen
,
arguments:
input
);
return
true
;
case
DirectionalScreenName
.
productMobileCard
:
Get
.
toNamed
(
productMobileCardScreen
);
return
true
;
case
DirectionalScreenName
.
simService
:
Get
.
toNamed
(
dataNetworkServiceScreen
);
return
true
;
case
DirectionalScreenName
.
pointBack
:
Get
.
toNamed
(
affiliateTabScreen
,
arguments:
{
"can_back_button"
:
true
});
return
true
;
case
DirectionalScreenName
.
gamesBundle
:
Get
.
toNamed
(
gameTabScreen
,
arguments:
{
"can_back_button"
:
true
});
return
true
;
case
DirectionalScreenName
.
vnTraPackage
||
DirectionalScreenName
.
familyMedon
:
Get
.
toNamed
(
voucherDetailScreen
,
arguments:
{
"productId"
:
int
.
parse
(
clickActionParam
??
""
)});
return
true
;
case
DirectionalScreenName
.
viewDeepLink
||
DirectionalScreenName
.
viewDeepLinkInApp
:
if
((
clickActionParam
??
""
).
isEmpty
)
return
true
;
const
replaceId1
=
'{{customerId}}'
;
const
replaceId2
=
'{customerId}'
;
final
customerId
=
DataPreference
.
instance
.
profile
?.
workerSite
?.
customerId
??
""
;
String
urlString
=
clickActionParam
!.
urlDecoded
;
if
(
urlString
.
contains
(
replaceId1
))
{
urlString
=
urlString
.
replaceAll
(
replaceId1
,
customerId
);
}
if
(
urlString
.
contains
(
replaceId2
))
{
urlString
=
urlString
.
replaceAll
(
replaceId2
,
customerId
);
}
// Parse thành Uri và thêm query aff_sub3
Uri
?
uri
=
Uri
.
tryParse
(
urlString
);
if
(
uri
==
null
)
return
true
;
final
requestId
=
const
Uuid
().
v4
();
// Cần package `uuid`
final
updatedUri
=
uri
.
replace
(
queryParameters:
{
...
uri
.
queryParameters
,
'aff_sub3'
:
requestId
,
});
LaunchMode
mode
=
type
==
DirectionalScreenName
.
viewDeepLink
?
LaunchMode
.
externalApplication
:
LaunchMode
.
platformDefault
;
forceOpen
(
url:
updatedUri
,
mode:
mode
);
return
true
;
case
DirectionalScreenName
.
refundHistory
:
Get
.
toNamed
(
historyPointCashBackScreen
);
return
true
;
default
:
default
:
print
(
"Không nhận diện được action type:
$clickActionType
"
);
print
(
"Không nhận diện được action type:
$clickActionType
"
);
return
false
;
return
false
;
}
}
}
}
}
}
Future
<
bool
>
forceOpen
({
required
Uri
url
,
LaunchMode
mode
=
LaunchMode
.
platformDefault
})
async
{
print
(
"force open
${url.toString()}
"
);
if
(
await
canLaunchUrl
(
url
))
{
await
launchUrl
(
url
,
mode:
LaunchMode
.
externalApplication
,
webViewConfiguration:
const
WebViewConfiguration
(
enableJavaScript:
true
,
headers:
<
String
,
String
>{},
),
);
return
true
;
}
return
false
;
}
Future
<
void
>
openAppStore
(
String
url
)
async
{
final
uri
=
Uri
.
parse
(
url
);
if
(
await
canLaunchUrl
(
uri
))
{
await
launchUrl
(
uri
,
mode:
LaunchMode
.
externalApplication
,
// ⚠️ Phải dùng mode này
);
}
else
{
debugPrint
(
"⚠️ Không thể mở URL:
$url
"
);
}
}
\ No newline at end of file
lib/extensions/num_extension.dart
View file @
fa01087d
...
@@ -33,8 +33,8 @@ enum CurrencyUnit {
...
@@ -33,8 +33,8 @@ enum CurrencyUnit {
eur
(
' EUR'
),
eur
(
' EUR'
),
none
(
' '
),
none
(
' '
),
noneSpace
(
''
),
noneSpace
(
''
),
VND
(
' VNĐ'
),
point
(
' điểm'
);
point
(
' điểm'
);
final
String
symbol
;
final
String
symbol
;
const
CurrencyUnit
(
this
.
symbol
);
const
CurrencyUnit
(
this
.
symbol
);
}
}
\ No newline at end of file
lib/extensions/string_extension.dart
View file @
fa01087d
...
@@ -9,6 +9,10 @@ extension PhoneValidator on String {
...
@@ -9,6 +9,10 @@ extension PhoneValidator on String {
}
}
}
}
extension
StringUrlExtension
on
String
{
String
get
urlDecoded
=>
Uri
.
decodeFull
(
this
);
}
extension
StringConvert
on
String
{
extension
StringConvert
on
String
{
String
toSha256
()
{
String
toSha256
()
{
var
bytes1
=
utf8
.
encode
(
this
);
var
bytes1
=
utf8
.
encode
(
this
);
...
...
lib/main.dart
View file @
fa01087d
import
'package:flutter/material.dart'
;
import
'package:flutter/material.dart'
;
import
'package:get/get.dart'
;
import
'package:get/get.dart'
;
import
'package:mypoint_flutter_app/preference/data_preference.dart'
;
import
'package:mypoint_flutter_app/preference/data_preference.dart'
;
import
'package:mypoint_flutter_app/preference/point/point_manager.dart'
;
import
'package:mypoint_flutter_app/shared/router_gage.dart'
;
import
'package:mypoint_flutter_app/shared/router_gage.dart'
;
void
main
(
)
async
{
void
main
(
)
async
{
WidgetsFlutterBinding
.
ensureInitialized
();
WidgetsFlutterBinding
.
ensureInitialized
();
await
DataPreference
.
instance
.
init
();
await
DataPreference
.
instance
.
init
();
await
UserPointManager
().
fetchUserPoint
();
runApp
(
const
MyApp
());
runApp
(
const
MyApp
());
}
}
...
...
lib/networking/restful_api_request.dart
View file @
fa01087d
...
@@ -13,8 +13,15 @@ import '../model/auth/login_token_response_model.dart';
...
@@ -13,8 +13,15 @@ import '../model/auth/login_token_response_model.dart';
import
'../model/auth/profile_response_model.dart'
;
import
'../model/auth/profile_response_model.dart'
;
import
'../model/update_response_model.dart'
;
import
'../model/update_response_model.dart'
;
import
'../preference/point/header_home_model.dart'
;
import
'../preference/point/header_home_model.dart'
;
import
'../screen/affiliate/model/affiliate_brand_model.dart'
;
import
'../screen/affiliate/model/affiliate_category_model.dart'
;
import
'../screen/affiliate/model/affiliate_product_top_sale_model.dart'
;
import
'../screen/affiliate/model/cashback_overview_model.dart'
;
import
'../screen/affiliate_brand_detail/models/affiliate_brand_detail_model.dart'
;
import
'../screen/data_network_service/product_network_data_model.dart'
;
import
'../screen/faqs/faqs_model.dart'
;
import
'../screen/faqs/faqs_model.dart'
;
import
'../screen/game/models/game_bundle_item_model.dart'
;
import
'../screen/game/models/game_bundle_item_model.dart'
;
import
'../screen/history_point_cashback/models/history_point_cashback_model.dart'
;
import
'../screen/home/models/achievement_model.dart'
;
import
'../screen/home/models/achievement_model.dart'
;
import
'../screen/home/models/hover_data_model.dart'
;
import
'../screen/home/models/hover_data_model.dart'
;
import
'../screen/home/models/main_section_config_model.dart'
;
import
'../screen/home/models/main_section_config_model.dart'
;
...
@@ -24,6 +31,9 @@ import '../screen/home/models/pipi_detail_model.dart';
...
@@ -24,6 +31,9 @@ import '../screen/home/models/pipi_detail_model.dart';
import
'../screen/location_address/models/district_address_model.dart'
;
import
'../screen/location_address/models/district_address_model.dart'
;
import
'../screen/location_address/models/province_address_model.dart'
;
import
'../screen/location_address/models/province_address_model.dart'
;
import
'../screen/membership/models/membership_info_response.dart'
;
import
'../screen/membership/models/membership_info_response.dart'
;
import
'../screen/mobile_card/models/mobile_service_redeem_data.dart'
;
import
'../screen/mobile_card/models/product_mobile_card_model.dart'
;
import
'../screen/mobile_card/models/usable_voucher_model.dart'
;
import
'../screen/notification/models/category_notify_item_model.dart'
;
import
'../screen/notification/models/category_notify_item_model.dart'
;
import
'../screen/notification/models/notification_detail_model.dart'
;
import
'../screen/notification/models/notification_detail_model.dart'
;
import
'../screen/notification/models/notification_list_data_model.dart'
;
import
'../screen/notification/models/notification_list_data_model.dart'
;
...
@@ -34,11 +44,8 @@ import '../screen/otp/model/otp_verify_response_model.dart';
...
@@ -34,11 +44,8 @@ import '../screen/otp/model/otp_verify_response_model.dart';
import
'../screen/pageDetail/model/campaign_detail_model.dart'
;
import
'../screen/pageDetail/model/campaign_detail_model.dart'
;
import
'../screen/pageDetail/model/detail_page_rule_type.dart'
;
import
'../screen/pageDetail/model/detail_page_rule_type.dart'
;
import
'../screen/register_campaign/model/registration_form_package_model.dart'
;
import
'../screen/register_campaign/model/registration_form_package_model.dart'
;
import
'../screen/shopping/model/affiliate_brand_model.dart'
;
import
'../screen/shopping/model/affiliate_category_model.dart'
;
import
'../screen/shopping/model/affiliate_product_top_sale_model.dart'
;
import
'../screen/shopping/model/cashback_overview_model.dart'
;
import
'../screen/splash/splash_screen_viewmodel.dart'
;
import
'../screen/splash/splash_screen_viewmodel.dart'
;
import
'../screen/topup/models/brand_network_model.dart'
;
import
'../screen/transaction/history/transaction_history_model.dart'
;
import
'../screen/transaction/history/transaction_history_model.dart'
;
import
'../screen/transaction/model/order_product_payment_response_model.dart'
;
import
'../screen/transaction/model/order_product_payment_response_model.dart'
;
import
'../screen/transaction/model/payment_bank_account_info_model.dart'
;
import
'../screen/transaction/model/payment_bank_account_info_model.dart'
;
...
@@ -46,7 +53,9 @@ import '../screen/transaction/model/payment_method_model.dart';
...
@@ -46,7 +53,9 @@ import '../screen/transaction/model/payment_method_model.dart';
import
'../screen/transaction/model/payment_method_type.dart'
;
import
'../screen/transaction/model/payment_method_type.dart'
;
import
'../screen/transaction/model/preview_order_payment_model.dart'
;
import
'../screen/transaction/model/preview_order_payment_model.dart'
;
import
'../screen/voucher/models/like_product_reponse_model.dart'
;
import
'../screen/voucher/models/like_product_reponse_model.dart'
;
import
'../screen/voucher/models/product_brand_model.dart'
;
import
'../screen/voucher/models/product_store_model.dart'
;
import
'../screen/voucher/models/product_store_model.dart'
;
import
'../screen/voucher/models/product_type.dart'
;
import
'../screen/voucher/models/search_product_response_model.dart'
;
import
'../screen/voucher/models/search_product_response_model.dart'
;
import
'model_maker.dart'
;
import
'model_maker.dart'
;
...
@@ -347,9 +356,12 @@ extension RestfullAPIClientAllApi on RestfulAPIClient {
...
@@ -347,9 +356,12 @@ extension RestfullAPIClientAllApi on RestfulAPIClient {
});
});
}
}
Future
<
BaseResponseModel
<
List
<
AffiliateBrandModel
>>>
affiliateBrandGetList
()
async
{
Future
<
BaseResponseModel
<
List
<
AffiliateBrandModel
>>>
affiliateBrandGetList
(
{
String
?
categoryCode
}
)
async
{
String
?
token
=
DataPreference
.
instance
.
token
??
""
;
String
?
token
=
DataPreference
.
instance
.
token
??
""
;
final
body
=
{
"access_token"
:
token
};
final
body
=
{
"access_token"
:
token
};
if
((
categoryCode
??
''
).
isNotEmpty
)
{
body
[
'category_code'
]
=
categoryCode
!;
}
return
requestNormal
(
APIPaths
.
affiliateBrandGetList
,
Method
.
POST
,
body
,
(
data
)
{
return
requestNormal
(
APIPaths
.
affiliateBrandGetList
,
Method
.
POST
,
body
,
(
data
)
{
final
list
=
data
as
List
<
dynamic
>;
final
list
=
data
as
List
<
dynamic
>;
return
list
.
map
((
e
)
=>
AffiliateBrandModel
.
fromJson
(
e
)).
toList
();
return
list
.
map
((
e
)
=>
AffiliateBrandModel
.
fromJson
(
e
)).
toList
();
...
@@ -458,10 +470,11 @@ extension RestfullAPIClientAllApi on RestfulAPIClient {
...
@@ -458,10 +470,11 @@ extension RestfullAPIClientAllApi on RestfulAPIClient {
int
?
paymentTokenId
,
int
?
paymentTokenId
,
bool
?
saveToken
,
bool
?
saveToken
,
String
?
metadata
,
String
?
metadata
,
String
?
targetPhoneNumber
,
})
async
{
})
async
{
final
items
=
final
items
=
products
.
map
((
product
)
{
products
.
map
((
product
)
{
return
{
'product_id'
:
product
.
id
,
'product_type'
:
product
.
type
??
''
,
'quantity'
:
quantity
};
return
{
'product_id'
:
product
.
id
,
'product_type'
:
product
.
type
??
''
,
'quantity'
:
quantity
,
'target_phone_number'
:
targetPhoneNumber
??
''
};
}).
toList
();
}).
toList
();
final
Map
<
String
,
dynamic
>
params
=
{
'request_id'
:
requestId
,
'items'
:
items
,
'flow'
:
'21'
};
final
Map
<
String
,
dynamic
>
params
=
{
'request_id'
:
requestId
,
'items'
:
items
,
'flow'
:
'21'
};
// flash_sale
// flash_sale
...
@@ -572,4 +585,97 @@ extension RestfullAPIClientAllApi on RestfulAPIClient {
...
@@ -572,4 +585,97 @@ extension RestfullAPIClientAllApi on RestfulAPIClient {
return
MembershipInfoResponse
.
fromJson
(
data
as
Json
);
return
MembershipInfoResponse
.
fromJson
(
data
as
Json
);
});
});
}
}
Future
<
BaseResponseModel
<
List
<
ProductBrandModel
>>>
getTopUpBrands
(
ProductType
type
)
async
{
final
body
=
{
"type"
:
type
.
value
};
return
requestNormal
(
APIPaths
.
getTopUpBrands
,
Method
.
GET
,
body
,
(
data
)
{
final
list
=
data
as
List
<
dynamic
>;
return
list
.
map
((
e
)
=>
ProductBrandModel
.
fromJson
(
e
)).
toList
();
});
}
Future
<
BaseResponseModel
<
List
<
ProductBrandModel
>>>
productTopUpBrands
()
async
{
final
body
=
{
"topup_type"
:
"PRODUCT_MODEL_MOBILE_SERVICE"
,
"page_size"
:
"999"
,
"page_index"
:
0
};
return
requestNormal
(
APIPaths
.
getTopUpBrands
,
Method
.
GET
,
body
,
(
data
)
{
final
list
=
data
as
List
<
dynamic
>;
return
list
.
map
((
e
)
=>
ProductBrandModel
.
fromJson
(
e
)).
toList
();
});
}
// productTopUpsBrands
Future
<
BaseResponseModel
<
BrandNameCheckResponse
>>
checkMobileNetwork
(
String
phone
)
async
{
final
body
=
{
"phone"
:
phone
};
return
requestNormal
(
APIPaths
.
checkMobileNetwork
,
Method
.
GET
,
body
,
(
data
)
{
return
BrandNameCheckResponse
.
fromJson
(
data
as
Json
);
});
}
Future
<
BaseResponseModel
<
ProductMobileCardResponse
>>
productMobileCardGetList
()
async
{
String
?
token
=
DataPreference
.
instance
.
token
??
""
;
final
body
=
{
"start"
:
0
,
"limit"
:
200
,
"access_token"
:
token
};
return
requestNormal
(
APIPaths
.
productMobileCardGetList
,
Method
.
POST
,
body
,
(
data
)
{
return
ProductMobileCardResponse
.
fromJson
(
data
as
Json
);
});
}
Future
<
BaseResponseModel
<
MobileServiceRedeemData
>>
redeemMobileCard
(
String
productId
)
async
{
String
?
token
=
DataPreference
.
instance
.
token
??
""
;
final
body
=
{
"product_id"
:
productId
,
"get_customer_balance"
:
"1"
,
"access_token"
:
token
};
return
requestNormal
(
APIPaths
.
redeemMobileCard
,
Method
.
POST
,
body
,
(
data
)
{
return
MobileServiceRedeemData
.
fromJson
(
data
as
Json
);
});
}
Future
<
BaseResponseModel
<
RedeemProductResponseModel
>>
getMobileCardCode
(
String
itemId
)
async
{
String
?
token
=
DataPreference
.
instance
.
token
??
""
;
final
body
=
{
"product_item_id"
:
itemId
,
"access_token"
:
token
};
return
requestNormal
(
APIPaths
.
redeemMobileCard
,
Method
.
POST
,
body
,
(
data
)
{
return
RedeemProductResponseModel
.
fromJson
(
data
as
Json
);
});
}
Future
<
BaseResponseModel
<
List
<
TopUpNetworkDataModel
>>>
getNetworkProducts
(
String
brandId
)
async
{
final
body
=
{
"brand_id"
:
brandId
,
"topup_type"
:
"PRODUCT_MODEL_MOBILE_SERVICE"
,
"page_size"
:
"999"
,
"page_index"
:
0
,
};
return
requestNormal
(
APIPaths
.
getNetworkProducts
,
Method
.
GET
,
body
,
(
data
)
{
final
list
=
data
as
List
<
dynamic
>;
return
list
.
map
((
e
)
=>
TopUpNetworkDataModel
.
fromJson
(
e
)).
toList
();
});
}
Future
<
BaseResponseModel
<
EmptyCodable
>>
redeemProductTopUps
(
String
productId
,
String
phoneNumber
)
async
{
String
?
token
=
DataPreference
.
instance
.
token
??
""
;
final
body
=
{
"access_token"
:
token
,
"product_id"
:
productId
,
"quantity"
:
1
,
"phone_number"
:
phoneNumber
,
};
return
requestNormal
(
APIPaths
.
redeemProductTopUps
,
Method
.
POST
,
body
,
(
data
)
{
return
EmptyCodable
.
fromJson
(
data
as
Json
);
});
}
Future
<
BaseResponseModel
<
HistoryPointCashBackResponse
>>
historyPointCashBackRequest
(
Json
body
)
async
{
String
?
token
=
DataPreference
.
instance
.
token
??
""
;
body
[
"access_token"
]
=
token
;
return
requestNormal
(
APIPaths
.
historyCashBackPoint
,
Method
.
GET
,
body
,
(
data
)
{
return
HistoryPointCashBackResponse
.
fromJson
(
data
as
Json
);
});
}
Future
<
BaseResponseModel
<
AffiliateBrandDetailModel
>>
getAffiliateBrandDetail
(
String
brandId
)
async
{
String
?
token
=
DataPreference
.
instance
.
token
??
""
;
final
body
=
{
"access_token"
:
token
,
"brand_id"
:
brandId
,
};
return
requestNormal
(
APIPaths
.
affiliateBrandGetDetail
,
Method
.
POST
,
body
,
(
data
)
{
return
AffiliateBrandDetailModel
.
fromJson
(
data
as
Json
);
});
}
}
}
\ No newline at end of file
lib/preference/contact_storage_service.dart
0 → 100644
View file @
fa01087d
import
'package:shared_preferences/shared_preferences.dart'
;
class
ContactStorageService
{
static
const
_keyUsedContacts
=
'used_contacts'
;
/// Lưu 1 số điện thoại vào danh sách đã dùng
Future
<
void
>
saveUsedContact
(
String
phone
)
async
{
final
prefs
=
await
SharedPreferences
.
getInstance
();
final
list
=
prefs
.
getStringList
(
_keyUsedContacts
)
??
[];
/// Nếu chưa có thì thêm vào đầu
if
(!
list
.
contains
(
phone
))
{
list
.
add
(
phone
);
await
prefs
.
setStringList
(
_keyUsedContacts
,
list
);
}
}
/// Lấy danh sách số đã dùng
Future
<
List
<
String
>>
getUsedContacts
()
async
{
final
prefs
=
await
SharedPreferences
.
getInstance
();
return
prefs
.
getStringList
(
_keyUsedContacts
)
??
[];
}
/// Xóa toàn bộ danh sách đã dùng (nếu cần)
Future
<
void
>
clearUsedContacts
()
async
{
final
prefs
=
await
SharedPreferences
.
getInstance
();
await
prefs
.
remove
(
_keyUsedContacts
);
}
}
lib/preference/data_preference.dart
View file @
fa01087d
...
@@ -23,7 +23,13 @@ class DataPreference {
...
@@ -23,7 +23,13 @@ class DataPreference {
_profile
=
ProfileResponseModel
.
fromJson
(
jsonDecode
(
profileJson
));
_profile
=
ProfileResponseModel
.
fromJson
(
jsonDecode
(
profileJson
));
}
}
}
}
String
get
fullName
=>
_profile
?.
workerSite
?.
fullname
??
"Quý Khách"
;
String
get
displayName
{
var
name
=
_profile
?.
workerSite
?.
fullname
??
""
;
if
(
name
.
isEmpty
)
{
name
=
"Quý Khách"
;
}
return
name
;
}
String
?
get
rankName
=>
_profile
?.
workingSite
?.
primaryMembership
?.
membershipLevel
?.
levelName
??
""
;
String
?
get
rankName
=>
_profile
?.
workingSite
?.
primaryMembership
?.
membershipLevel
?.
levelName
??
""
;
String
?
get
token
=>
_loginToken
?.
accessToken
;
String
?
get
token
=>
_loginToken
?.
accessToken
;
String
?
get
phone
=>
_profile
?.
workerSite
?.
phoneNumber
;
String
?
get
phone
=>
_profile
?.
workerSite
?.
phoneNumber
;
...
...
lib/screen/
shopping
/affiliate_overview.dart
→
lib/screen/
affiliate
/affiliate_overview.dart
View file @
fa01087d
File moved
lib/screen/affiliate/affiliate_popup_brands.dart
0 → 100644
View file @
fa01087d
import
'package:flutter/material.dart'
;
import
'package:get/get.dart'
;
import
'package:mypoint_flutter_app/resouce/base_color.dart'
;
import
'package:mypoint_flutter_app/widgets/image_loader.dart'
;
import
'../../shared/router_gage.dart'
;
import
'model/affiliate_brand_model.dart'
;
void
showAffiliateBrandPopup
(
BuildContext
context
,
List
<
AffiliateBrandModel
>
brands
,
{
String
?
title
})
{
showModalBottomSheet
(
context:
context
,
isScrollControlled:
true
,
backgroundColor:
Colors
.
white
,
shape:
const
RoundedRectangleBorder
(
borderRadius:
BorderRadius
.
vertical
(
top:
Radius
.
circular
(
16
))),
builder:
(
_
)
{
return
SafeArea
(
child:
Column
(
mainAxisSize:
MainAxisSize
.
min
,
children:
[
const
SizedBox
(
height:
8
),
Row
(
children:
[
const
SizedBox
(
width:
16
),
Expanded
(
child:
Center
(
child:
Text
(
title
??
"Thương hiệu"
,
style:
const
TextStyle
(
fontSize:
18
,
fontWeight:
FontWeight
.
bold
,
color:
Colors
.
black
),
),
),
),
IconButton
(
icon:
const
Icon
(
Icons
.
close
),
onPressed:
()
=>
Navigator
.
of
(
context
).
pop
()),
// const SizedBox(width: 8),
],
),
const
Divider
(
height:
1
),
Flexible
(
child:
ListView
.
separated
(
shrinkWrap:
true
,
padding:
const
EdgeInsets
.
symmetric
(
vertical:
8
),
itemCount:
brands
.
length
,
separatorBuilder:
(
_
,
__
)
=>
const
SizedBox
(
height:
4
),
itemBuilder:
(
context
,
index
)
{
final
brand
=
brands
[
index
];
return
GestureDetector
(
onTap:
()
{
Navigator
.
of
(
context
).
pop
();
Get
.
toNamed
(
affiliateBrandDetailScreen
,
arguments:
{
"brandId"
:
brand
.
brandId
});
},
child:
Padding
(
padding:
const
EdgeInsets
.
only
(
left:
16
,
right:
16
,
bottom:
8
),
child:
Container
(
padding:
const
EdgeInsets
.
all
(
12
),
decoration:
BoxDecoration
(
border:
Border
.
all
(
color:
Colors
.
grey
.
shade300
),
borderRadius:
BorderRadius
.
circular
(
12
),
),
child:
Row
(
children:
[
ClipRRect
(
borderRadius:
BorderRadius
.
circular
(
40
),
child:
loadNetworkImage
(
url:
brand
.
logo
,
width:
60
,
height:
60
,
placeholderAsset:
"assets/images/ic_logo.png"
,
),
),
const
SizedBox
(
width:
12
),
Expanded
(
child:
Column
(
crossAxisAlignment:
CrossAxisAlignment
.
start
,
children:
[
Text
(
brand
.
brandName
??
''
,
style:
const
TextStyle
(
fontWeight:
FontWeight
.
bold
,
fontSize:
16
),
),
const
SizedBox
(
height:
4
),
RichText
(
text:
TextSpan
(
text:
'Hoàn đến: '
,
style:
const
TextStyle
(
color:
Colors
.
black54
,
fontSize:
13
),
children:
[
TextSpan
(
text:
brand
.
showCommision
??
''
,
style:
const
TextStyle
(
color:
Colors
.
deepOrange
,
fontWeight:
FontWeight
.
bold
,
fontSize:
14
),
),
],
),
),
],
),
),
ElevatedButton
(
style:
ElevatedButton
.
styleFrom
(
backgroundColor:
BaseColor
.
primary500
,
shape:
RoundedRectangleBorder
(
borderRadius:
BorderRadius
.
circular
(
12
)),
padding:
const
EdgeInsets
.
symmetric
(
horizontal:
16
,
vertical:
8
),
),
onPressed:
()
{
Navigator
.
of
(
context
).
pop
();
brand
.
directionalScreen
?.
begin
();
},
child:
const
Text
(
"Mua ngay"
,
style:
TextStyle
(
color:
Colors
.
white
,
fontSize:
14
,
fontWeight:
FontWeight
.
w600
),
),
),
],
),
),
),
);
},
),
),
],
),
);
},
);
}
lib/screen/
shopping
/affiliate_tab_screen.dart
→
lib/screen/
affiliate
/affiliate_tab_screen.dart
View file @
fa01087d
import
'package:flutter/material.dart'
;
import
'package:flutter/material.dart'
;
import
'package:get/get.dart'
;
import
'package:get/get.dart'
;
import
'package:mypoint_flutter_app/screen/
shopping
/sub_widget/build_affiliate_brand.dart'
;
import
'package:mypoint_flutter_app/screen/
affiliate
/sub_widget/build_affiliate_brand.dart'
;
import
'package:mypoint_flutter_app/screen/
shopping
/sub_widget/build_affiliate_category.dart'
;
import
'package:mypoint_flutter_app/screen/
affiliate
/sub_widget/build_affiliate_category.dart'
;
import
'package:mypoint_flutter_app/screen/
shopping
/sub_widget/build_affiliate_product_topsale.dart'
;
import
'package:mypoint_flutter_app/screen/
affiliate
/sub_widget/build_affiliate_product_topsale.dart'
;
import
'../../base/base_screen.dart'
;
import
'../../base/base_screen.dart'
;
import
'../../base/basic_state.dart'
;
import
'../../base/basic_state.dart'
;
import
'../../resouce/base_color.dart'
;
import
'../../resouce/base_color.dart'
;
import
'../../shared/router_gage.dart'
;
import
'../../widgets/bottom_sheet_helper.dart'
;
import
'../../widgets/bottom_sheet_helper.dart'
;
import
'../../widgets/custom_navigation_bar.dart'
;
import
'../../widgets/custom_navigation_bar.dart'
;
import
'../home/header_home_viewmodel.dart'
;
import
'../home/header_home_viewmodel.dart'
;
import
'affiliate_overview.dart'
;
import
'affiliate_overview.dart'
;
import
'affiliate_popup_brands.dart'
;
import
'affiliate_tab_viewmodel.dart'
;
import
'affiliate_tab_viewmodel.dart'
;
import
'model/affiliate_category_type.dart'
;
class
AffiliateTabScreen
extends
BaseScreen
{
class
AffiliateTabScreen
extends
BaseScreen
{
const
AffiliateTabScreen
({
super
.
key
});
const
AffiliateTabScreen
({
super
.
key
});
...
@@ -22,6 +25,19 @@ class AffiliateTabScreen extends BaseScreen {
...
@@ -22,6 +25,19 @@ class AffiliateTabScreen extends BaseScreen {
class
_AffiliateTabScreenState
extends
BaseState
<
AffiliateTabScreen
>
with
BasicState
{
class
_AffiliateTabScreenState
extends
BaseState
<
AffiliateTabScreen
>
with
BasicState
{
final
AffiliateTabViewModel
viewModel
=
Get
.
put
(
AffiliateTabViewModel
());
final
AffiliateTabViewModel
viewModel
=
Get
.
put
(
AffiliateTabViewModel
());
final
_headerHomeVM
=
Get
.
find
<
HeaderHomeViewModel
>();
final
_headerHomeVM
=
Get
.
find
<
HeaderHomeViewModel
>();
late
var
_canBackButton
=
false
;
@override
void
initState
()
{
super
.
initState
();
final
args
=
Get
.
arguments
;
if
(
args
is
Map
)
{
_canBackButton
=
args
[
'can_back_button'
]
as
bool
;
}
viewModel
.
onShowAffiliateBrandPopup
=
(
data
)
{
showAffiliateBrandPopup
(
context
,
data
.
$
1
,
title:
data
.
$
2
);
};
}
@override
@override
Widget
createBody
()
{
Widget
createBody
()
{
...
@@ -29,7 +45,7 @@ class _AffiliateTabScreenState extends BaseState<AffiliateTabScreen> with BasicS
...
@@ -29,7 +45,7 @@ class _AffiliateTabScreenState extends BaseState<AffiliateTabScreen> with BasicS
backgroundColor:
Colors
.
grey
.
shade50
,
backgroundColor:
Colors
.
grey
.
shade50
,
appBar:
CustomNavigationBar
(
appBar:
CustomNavigationBar
(
title:
"Mua sắm"
,
title:
"Mua sắm"
,
showBackButton:
false
,
showBackButton:
_canBackButton
,
backgroundImage:
_headerHomeVM
.
headerData
.
background
??
"assets/images/bg_header_navi.png"
,
backgroundImage:
_headerHomeVM
.
headerData
.
background
??
"assets/images/bg_header_navi.png"
,
rightButtons:
[
rightButtons:
[
IconButton
(
IconButton
(
...
@@ -57,22 +73,27 @@ class _AffiliateTabScreenState extends BaseState<AffiliateTabScreen> with BasicS
...
@@ -57,22 +73,27 @@ class _AffiliateTabScreenState extends BaseState<AffiliateTabScreen> with BasicS
crossAxisAlignment:
CrossAxisAlignment
.
start
,
crossAxisAlignment:
CrossAxisAlignment
.
start
,
mainAxisAlignment:
MainAxisAlignment
.
start
,
mainAxisAlignment:
MainAxisAlignment
.
start
,
children:
[
children:
[
Container
(
GestureDetector
(
padding:
const
EdgeInsets
.
all
(
12
),
onTap:
()
{
decoration:
BoxDecoration
(
color:
Colors
.
amber
.
shade100
,
borderRadius:
BorderRadius
.
circular
(
12
)),
Get
.
toNamed
(
historyPointCashBackScreen
);
child:
Row
(
},
children:
[
child:
Container
(
const
Text
(
"Điểm hoàn:"
,
style:
TextStyle
(
fontSize:
18
,
fontWeight:
FontWeight
.
normal
)),
padding:
const
EdgeInsets
.
all
(
12
),
const
SizedBox
(
width:
8
),
decoration:
BoxDecoration
(
color:
Colors
.
amber
.
shade100
,
borderRadius:
BorderRadius
.
circular
(
12
)),
Image
.
asset
(
'assets/images/ic_point.png'
,
width:
20
,
height:
20
),
child:
Row
(
const
SizedBox
(
width:
4
),
children:
[
const
Text
(
const
Text
(
"Điểm hoàn:"
,
style:
TextStyle
(
fontSize:
18
,
fontWeight:
FontWeight
.
normal
)),
"0"
,
const
SizedBox
(
width:
8
),
style:
TextStyle
(
fontSize:
20
,
color:
BaseColor
.
primary400
,
fontWeight:
FontWeight
.
bold
),
Image
.
asset
(
'assets/images/ic_point.png'
,
width:
20
,
height:
20
),
),
const
SizedBox
(
width:
4
),
const
Spacer
(),
const
Text
(
Icon
(
Icons
.
arrow_forward_ios
,
color:
BaseColor
.
primary400
,
size:
16
),
"0"
,
],
style:
TextStyle
(
fontSize:
20
,
color:
BaseColor
.
primary400
,
fontWeight:
FontWeight
.
bold
),
),
const
Spacer
(),
Icon
(
Icons
.
arrow_forward_ios
,
color:
BaseColor
.
primary400
,
size:
16
),
],
),
),
),
),
),
const
SizedBox
(
height:
16
),
const
SizedBox
(
height:
16
),
...
@@ -92,7 +113,13 @@ class _AffiliateTabScreenState extends BaseState<AffiliateTabScreen> with BasicS
...
@@ -92,7 +113,13 @@ class _AffiliateTabScreenState extends BaseState<AffiliateTabScreen> with BasicS
),
),
),
),
AffiliateBrand
(
brands:
viewModel
.
affiliateBrands
),
AffiliateBrand
(
brands:
viewModel
.
affiliateBrands
),
AffiliateCategory
(
categories:
viewModel
.
affiliateCategories
),
AffiliateCategory
(
categories:
viewModel
.
affiliateCategories
,
onTap:
(
category
)
{
if
(
category
.
code
==
AffiliateCategoryType
.
other
)
{
Get
.
toNamed
(
affiliateCategoryGridScreen
,
arguments:
{
"categories"
:
viewModel
.
allAffiliateCategories
});
return
;
}
viewModel
.
affiliateBrandGetListBuyCategory
(
category
);
},),
AffiliateProductTopSale
(
products:
viewModel
.
affiliateProducts
),
AffiliateProductTopSale
(
products:
viewModel
.
affiliateProducts
),
],
],
),
),
...
...
lib/screen/
shopping
/affiliate_tab_viewmodel.dart
→
lib/screen/
affiliate
/affiliate_tab_viewmodel.dart
View file @
fa01087d
import
'package:get/get_rx/src/rx_types/rx_types.dart'
;
import
'package:get/get_rx/src/rx_types/rx_types.dart'
;
import
'package:mypoint_flutter_app/networking/restful_api_request.dart'
;
import
'package:mypoint_flutter_app/networking/restful_api_request.dart'
;
import
'../../base/restful_api_viewmodel.dart'
;
import
'../../base/restful_api_viewmodel.dart'
;
import
'affiliate_popup_brands.dart'
;
import
'model/affiliate_brand_model.dart'
;
import
'model/affiliate_brand_model.dart'
;
import
'model/affiliate_category_model.dart'
;
import
'model/affiliate_category_model.dart'
;
import
'model/affiliate_category_type.dart'
;
import
'model/affiliate_category_type.dart'
;
...
@@ -10,9 +11,11 @@ import 'model/cashback_overview_model.dart';
...
@@ -10,9 +11,11 @@ import 'model/cashback_overview_model.dart';
class
AffiliateTabViewModel
extends
RestfulApiViewModel
{
class
AffiliateTabViewModel
extends
RestfulApiViewModel
{
final
RxList
<
AffiliateBrandModel
>
affiliateBrands
=
<
AffiliateBrandModel
>[].
obs
;
final
RxList
<
AffiliateBrandModel
>
affiliateBrands
=
<
AffiliateBrandModel
>[].
obs
;
final
RxList
<
AffiliateCategoryModel
>
affiliateCategories
=
<
AffiliateCategoryModel
>[].
obs
;
final
RxList
<
AffiliateCategoryModel
>
affiliateCategories
=
<
AffiliateCategoryModel
>[].
obs
;
final
RxList
<
AffiliateCategoryModel
>
allAffiliateCategories
=
<
AffiliateCategoryModel
>[].
obs
;
final
RxList
<
AffiliateProductTopSaleModel
>
affiliateProducts
=
<
AffiliateProductTopSaleModel
>[].
obs
;
final
RxList
<
AffiliateProductTopSaleModel
>
affiliateProducts
=
<
AffiliateProductTopSaleModel
>[].
obs
;
final
RxBool
isLoading
=
false
.
obs
;
final
RxBool
isLoading
=
false
.
obs
;
var
overview
=
Rxn
<
CashbackOverviewModel
>();
var
overview
=
Rxn
<
CashbackOverviewModel
>();
void
Function
((
List
<
AffiliateBrandModel
>,
String
)
data
)?
onShowAffiliateBrandPopup
;
@override
@override
void
onInit
()
{
void
onInit
()
{
...
@@ -34,7 +37,7 @@ class AffiliateTabViewModel extends RestfulApiViewModel {
...
@@ -34,7 +37,7 @@ class AffiliateTabViewModel extends RestfulApiViewModel {
Future
<
void
>
_getAffiliateBrandGetList
()
async
{
Future
<
void
>
_getAffiliateBrandGetList
()
async
{
try
{
try
{
final
result
=
await
client
.
affiliateBrandGetList
();
final
result
=
await
client
.
affiliateBrandGetList
();
affiliateBrands
.
value
=
(
result
.
data
??
[]
).
take
(
6
).
toList
()
;
affiliateBrands
.
value
=
result
.
data
??
[];
}
catch
(
error
)
{
}
catch
(
error
)
{
print
(
"Error fetching affiliate brands:
$error
"
);
print
(
"Error fetching affiliate brands:
$error
"
);
}
}
...
@@ -47,7 +50,10 @@ class AffiliateTabViewModel extends RestfulApiViewModel {
...
@@ -47,7 +50,10 @@ class AffiliateTabViewModel extends RestfulApiViewModel {
code:
AffiliateCategoryType
.
other
,
code:
AffiliateCategoryType
.
other
,
name:
"Khác"
,
name:
"Khác"
,
);
);
final
data
=
(
result
.
data
??
[]).
take
(
7
).
toList
();
final
results
=
(
result
.
data
??
[]);
allAffiliateCategories
.
value
=
results
;
final
data
=
results
.
take
(
7
).
toList
();
data
.
add
(
category
);
data
.
add
(
category
);
affiliateCategories
.
value
=
data
;
affiliateCategories
.
value
=
data
;
}
catch
(
error
)
{
}
catch
(
error
)
{
...
@@ -72,4 +78,19 @@ class AffiliateTabViewModel extends RestfulApiViewModel {
...
@@ -72,4 +78,19 @@ class AffiliateTabViewModel extends RestfulApiViewModel {
print
(
"Error fetching affiliate brands:
$error
"
);
print
(
"Error fetching affiliate brands:
$error
"
);
}
}
}
}
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
"
);
}
}
}
}
\ No newline at end of file
lib/screen/
shopping
/model/affiliate_brand_model.dart
→
lib/screen/
affiliate
/model/affiliate_brand_model.dart
View file @
fa01087d
import
'package:json_annotation/json_annotation.dart'
;
import
'package:json_annotation/json_annotation.dart'
;
import
'../../../configs/constants.dart'
;
import
'../../../directional/directional_action_type.dart'
;
import
'../../../directional/directional_screen.dart'
;
part
'affiliate_brand_model.g.dart'
;
part
'affiliate_brand_model.g.dart'
;
@JsonSerializable
()
@JsonSerializable
()
...
@@ -25,6 +28,18 @@ class AffiliateBrandModel {
...
@@ -25,6 +28,18 @@ class AffiliateBrandModel {
this
.
direction
,
this
.
direction
,
});
});
DirectionalScreen
?
get
directionalScreen
{
if
(
brandUrl
==
null
||
brandUrl
!.
isEmpty
)
return
null
;
if
(
direction
==
Constants
.
directionInApp
)
{
return
DirectionalScreen
.
buildByName
(
name:
DirectionalScreenName
.
viewDeepLinkInApp
,
clickActionParam:
brandUrl
);
}
return
DirectionalScreen
.
buildByName
(
name:
DirectionalScreenName
.
viewDeepLink
,
clickActionParam:
brandUrl
);
}
String
get
showCommision
{
return
'
${double.tryParse(commision ?? '0')?.toStringAsFixed(1) ?? '0.0'}
%'
;
}
factory
AffiliateBrandModel
.
fromJson
(
Map
<
String
,
dynamic
>
json
)
=>
_$AffiliateBrandModelFromJson
(
json
);
factory
AffiliateBrandModel
.
fromJson
(
Map
<
String
,
dynamic
>
json
)
=>
_$AffiliateBrandModelFromJson
(
json
);
Map
<
String
,
dynamic
>
toJson
()
=>
_$AffiliateBrandModelToJson
(
this
);
Map
<
String
,
dynamic
>
toJson
()
=>
_$AffiliateBrandModelToJson
(
this
);
}
}
lib/screen/
shopping
/model/affiliate_brand_model.g.dart
→
lib/screen/
affiliate
/model/affiliate_brand_model.g.dart
View file @
fa01087d
File moved
lib/screen/
shopping
/model/affiliate_category_model.dart
→
lib/screen/
affiliate
/model/affiliate_category_model.dart
View file @
fa01087d
...
@@ -2,10 +2,9 @@ import 'package:json_annotation/json_annotation.dart';
...
@@ -2,10 +2,9 @@ import 'package:json_annotation/json_annotation.dart';
import
'affiliate_category_type.dart'
;
import
'affiliate_category_type.dart'
;
part
'affiliate_category_model.g.dart'
;
part
'affiliate_category_model.g.dart'
;
@JsonSerializable
()
@JsonSerializable
()
class
AffiliateCategoryModel
{
class
AffiliateCategoryModel
{
@JsonKey
(
name:
"category_code"
,
fromJson:
_codeFromJson
,
toJson:
_
codeToJson
)
@JsonKey
(
name:
"category_code"
,
fromJson:
_codeFromJson
,
toJson:
codeToJson
)
final
AffiliateCategoryType
code
;
final
AffiliateCategoryType
code
;
@JsonKey
(
name:
"category_name"
)
@JsonKey
(
name:
"category_name"
)
...
@@ -19,19 +18,16 @@ class AffiliateCategoryModel {
...
@@ -19,19 +18,16 @@ class AffiliateCategoryModel {
static
AffiliateCategoryType
_codeFromJson
(
String
code
)
=>
static
AffiliateCategoryType
_codeFromJson
(
String
code
)
=>
affiliateCategoryTypeValues
[
code
]
??
AffiliateCategoryType
.
other
;
affiliateCategoryTypeValues
[
code
]
??
AffiliateCategoryType
.
other
;
static
String
_
codeToJson
(
AffiliateCategoryType
type
)
=>
static
String
codeToJson
(
AffiliateCategoryType
type
)
=>
affiliateCategoryTypeValues
.
entries
affiliateCategoryTypeValues
.
entries
.
firstWhere
((
e
)
=>
e
.
value
==
type
,
.
firstWhere
((
e
)
=>
e
.
value
==
type
,
orElse:
()
=>
const
MapEntry
(
"other"
,
AffiliateCategoryType
.
other
))
orElse:
()
=>
const
MapEntry
(
"other"
,
AffiliateCategoryType
.
other
))
.
key
;
.
key
;
String
get
icon
=>
"ic_cashback_
${
_
codeToJson(code)}
"
;
String
get
icon
=>
"ic_cashback_
${codeToJson(code)}
"
;
bool
get
isOther
=>
code
==
AffiliateCategoryType
.
other
;
bool
get
isOther
=>
code
==
AffiliateCategoryType
.
other
;
static
AffiliateCategoryModel
get
other
=>
AffiliateCategoryModel
(
code:
AffiliateCategoryType
.
other
,
name:
"Khác"
);
factory
AffiliateCategoryModel
.
fromJson
(
Map
<
String
,
dynamic
>
json
)
=>
factory
AffiliateCategoryModel
.
fromJson
(
Map
<
String
,
dynamic
>
json
)
=>
_$AffiliateCategoryModelFromJson
(
json
);
_$AffiliateCategoryModelFromJson
(
json
);
...
...
lib/screen/
shopping
/model/affiliate_category_model.g.dart
→
lib/screen/
affiliate
/model/affiliate_category_model.g.dart
View file @
fa01087d
...
@@ -16,6 +16,6 @@ AffiliateCategoryModel _$AffiliateCategoryModelFromJson(
...
@@ -16,6 +16,6 @@ AffiliateCategoryModel _$AffiliateCategoryModelFromJson(
Map
<
String
,
dynamic
>
_$AffiliateCategoryModelToJson
(
Map
<
String
,
dynamic
>
_$AffiliateCategoryModelToJson
(
AffiliateCategoryModel
instance
,
AffiliateCategoryModel
instance
,
)
=>
<
String
,
dynamic
>{
)
=>
<
String
,
dynamic
>{
'category_code'
:
AffiliateCategoryModel
.
_
codeToJson
(
instance
.
code
),
'category_code'
:
AffiliateCategoryModel
.
codeToJson
(
instance
.
code
),
'category_name'
:
instance
.
name
,
'category_name'
:
instance
.
name
,
};
};
lib/screen/
shopping
/model/affiliate_category_type.dart
→
lib/screen/
affiliate
/model/affiliate_category_type.dart
View file @
fa01087d
File moved
lib/screen/
shopping
/model/affiliate_product_top_sale_model.dart
→
lib/screen/
affiliate
/model/affiliate_product_top_sale_model.dart
View file @
fa01087d
import
'package:json_annotation/json_annotation.dart'
;
import
'package:json_annotation/json_annotation.dart'
;
import
'package:mypoint_flutter_app/directional/directional_screen.dart'
;
import
'../../../directional/directional_action_type.dart'
;
part
'affiliate_product_top_sale_model.g.dart'
;
part
'affiliate_product_top_sale_model.g.dart'
;
@JsonSerializable
()
@JsonSerializable
()
...
@@ -17,6 +20,20 @@ class AffiliateProductTopSaleModel {
...
@@ -17,6 +20,20 @@ class AffiliateProductTopSaleModel {
final
String
?
quantitySold
;
final
String
?
quantitySold
;
final
String
?
direction
;
final
String
?
direction
;
DirectionalScreen
?
get
direcionalScreen
{
if
((
productLink
??
""
).
isEmpty
)
return
null
;
if
(
direction
==
"IN-APP"
)
{
return
DirectionalScreen
.
buildByName
(
name:
DirectionalScreenName
.
viewDeepLinkInApp
,
clickActionParam:
productLink
,
);
}
return
DirectionalScreen
.
buildByName
(
name:
DirectionalScreenName
.
viewDeepLink
,
clickActionParam:
productLink
,
);
}
AffiliateProductTopSaleModel
({
AffiliateProductTopSaleModel
({
this
.
productName
,
this
.
productName
,
this
.
productPrice
,
this
.
productPrice
,
...
...
lib/screen/
shopping
/model/affiliate_product_top_sale_model.g.dart
→
lib/screen/
affiliate
/model/affiliate_product_top_sale_model.g.dart
View file @
fa01087d
File moved
Prev
1
2
3
4
5
6
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