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
75178f29
Commit
75178f29
authored
May 27, 2025
by
DatHV
Browse files
update notify screen,
voucher QR code
parent
33ec1dde
Changes
24
Show whitespace changes
Inline
Side-by-side
assets/images/ic_scan_tutorial.png
0 → 100644
View file @
75178f29
39.2 KB
lib/configs/api_paths.dart
View file @
75178f29
...
...
@@ -50,4 +50,6 @@ class APIPaths {
static
const
String
deleteNotification
=
"/notificationDeleteOne/1.0.0"
;
static
const
String
deleteAllNotifications
=
"/notificationDeleteAll/1.0.0"
;
static
const
String
notificationMarkAsSeen
=
"/notificationMarkAsSeen/1.0.0"
;
static
const
String
notificationGetDetail
=
"/notificationGetDetail/1.0.0"
;
static
const
String
getCustomerProductDetail
=
"/product/api/v2.0/customer/products/%@"
;
}
\ No newline at end of file
lib/directional/directional_action_type.dart
View file @
75178f29
enum
ClickActionType
{
campaignDetail
,
import
'../shared/router_gage.dart'
;
enum
DirectionalScreenName
{
flashSale
,
searchProduct
,
setting
,
cashBackPointPartnerDetail
,
notifications
,
notification
,
appScreen
,
website
,
voucher
,
productOwnVoucher
,
myMobileCard
,
brand
,
transaction
,
link
,
viewDeepLink
,
viewDeepLinkInApp
,
viewGift
,
feedback
,
dailyCheckin
,
dailyCheckinScreen
,
inputReferralCode
,
myPurchaseItems
,
myPurchaseItemsWaitingList
,
achievement
,
productVoucherLike
,
productMobileCard
,
workerProfile
,
customerInviteFriend
,
customerTransferPoint
,
customerReviewApp
,
preferentialHotList
,
pointHistory
,
refundHistory
,
home
,
pointBack
,
brandList
,
news
,
brandLike
,
productVoucher
,
memberShip
,
ranking
,
mobileTopup
,
mobileTopupData
,
topup
,
register
,
gifts
,
viewSMS
,
walkingCampaign
,
applicationSetting
,
customerSupport
,
historyInvitedFriend
,
gameWorldCup2022
,
rateStorePopup
,
simService
,
vietlott
,
shoppingOnline
,
electricBill
,
partnerRedirect
,
brandOffline
,
pipiScreen
,
campaignSevenDayScreen
,
surveyCampaign
,
inviteFriend
,
viewVoucherWithCountTime
,
viewAllVoucher
,
popViewController
,
finishScreen
,
screenAddInvitationCode
,
luckyMoney
,
termPolicyDeleteAccount
,
privacyPolicy
,
termsOfUse
,
termPolicyDecree13
,
bankAccountManager
,
familyMedon
,
familyMedonDetailCard
,
familyHealthBook
,
gameCenter
,
vnTraPackage
,
myVnTraPackage
,
detailTrafficService
,
makeDirectionScreen
,
webviewFullScreen
,
gamesBundle
,
gameCardDetail
,
newInviteFriend
,
inviteFriendApply
,
personal
,
voucherTab
,
introduction
,
listPaymentOfElectric
,
favorite
,
unknown
,
}
extension
ClickActionTypeExtension
on
ClickActionType
{
String
get
key
{
// const splashScreen = '/splash';
// const onboardingScreen = '/onboarding';
// const loginScreen = '/login';
// const mainScreen = '/main';
// const vouchersScreen = '/vouchers';
// const gameCardScreen = '/gameCardScreen';
// const registerFormInputScreen = '/registerFormInputScreen';
// const transactionDetailScreen = '/transactionDetailScreen';
// const baseWebViewScreen = '/baseWebViewScreen';
// const paymentWebViewScreen = '/paymentWebViewScreen';
// const transactionHistoryDetailScreen = '/transactionHistoryDetailScreen';
extension
DirectionalScreenRouterExtension
on
DirectionalScreenName
{
String
get
router
{
switch
(
this
)
{
case
ClickActionType
.
campaignDetail
:
return
"campaignDetail"
;
case
DirectionalScreenName
.
setting
:
return
settingScreen
;
case
DirectionalScreenName
.
notifications
:
return
notificationScreen
;
case
DirectionalScreenName
.
home
:
return
mainScreen
;
case
DirectionalScreenName
.
productOwnVoucher
:
return
voucherDetailScreen
;
case
DirectionalScreenName
.
customerSupport
:
return
supportScreen
;
default
:
return
''
;
}
}
}
static
ClickActionType
?
fromString
(
String
value
)
{
switch
(
value
)
{
case
"campaignDetail"
:
return
ClickActionType
.
campaignDetail
;
default
:
return
null
;
extension
DirectionalScreenNameExtension
on
DirectionalScreenName
{
String
get
rawValue
{
switch
(
this
)
{
case
DirectionalScreenName
.
flashSale
:
return
"APP_SCREEN_FLASH_SALE"
;
case
DirectionalScreenName
.
searchProduct
:
return
"APP_SCREEN_SEARCH_PRODUCTS"
;
case
DirectionalScreenName
.
setting
:
return
"APP_SCREEN_SETTING"
;
case
DirectionalScreenName
.
cashBackPointPartnerDetail
:
return
"APP_SCREEN_CASHBACK_PARTNER_DETAIL"
;
case
DirectionalScreenName
.
notifications
:
return
"APP_SCREEN_NOTIFICATIONS"
;
case
DirectionalScreenName
.
notification
:
return
"NOTIFICATION_DETAIL"
;
case
DirectionalScreenName
.
appScreen
:
return
"VIEW_APP_SCREEN"
;
case
DirectionalScreenName
.
website
:
return
"VIEW_WEBSITE_PAGE"
;
case
DirectionalScreenName
.
voucher
:
return
"VIEW_PRODUCT_VOUCHER"
;
case
DirectionalScreenName
.
productOwnVoucher
:
return
"VIEW_PRODUCT_OWN_VOUCHER"
;
case
DirectionalScreenName
.
myMobileCard
:
return
"VIEW_MY_MOBILE_CARD"
;
case
DirectionalScreenName
.
brand
:
return
"VIEW_BRAND"
;
case
DirectionalScreenName
.
transaction
:
return
"VIEW_TRANSACTION_REQUEST"
;
case
DirectionalScreenName
.
link
:
return
"VIEW_LINK"
;
case
DirectionalScreenName
.
viewDeepLink
:
return
"VIEW_DEEP_LINK"
;
case
DirectionalScreenName
.
viewDeepLinkInApp
:
return
"VIEW_DEEP_LINK_INAPP"
;
case
DirectionalScreenName
.
viewGift
:
return
"VIEW_GIFT"
;
case
DirectionalScreenName
.
feedback
:
return
"FEEDBACK"
;
case
DirectionalScreenName
.
dailyCheckin
:
return
"DAILY_CHECKIN"
;
case
DirectionalScreenName
.
dailyCheckinScreen
:
return
"APP_SCREEN_CUSTOMER_DAILY_CHECKIN"
;
case
DirectionalScreenName
.
inputReferralCode
:
return
"INPUT_REFERRAL_CODE"
;
case
DirectionalScreenName
.
myPurchaseItems
:
return
"APP_SCREEN_MY_PURCHASE_ITEMS"
;
case
DirectionalScreenName
.
myPurchaseItemsWaitingList
:
return
"APP_SCREEN_MY_PURCHASE_ITEMS-WAITING_LIST"
;
case
DirectionalScreenName
.
achievement
:
return
"APP_SCREEN_ACHIEVEMENT"
;
case
DirectionalScreenName
.
productVoucherLike
:
return
"APP_SCREEN_PRODUCT_VOUCHER_LIKES"
;
case
DirectionalScreenName
.
productMobileCard
:
return
"APP_SCREEN_PRODUCT_MOBILE_CARD"
;
case
DirectionalScreenName
.
workerProfile
:
return
"APP_SCREEN_WORKER_PROFILE"
;
case
DirectionalScreenName
.
customerInviteFriend
:
return
"APP_SCREEN_CUSTOMER_INVITE_FRIEND"
;
case
DirectionalScreenName
.
customerTransferPoint
:
return
"APP_SCREEN_CUSTOMER_TRANSFERT_POINT"
;
case
DirectionalScreenName
.
customerReviewApp
:
return
"APP_SCREEN_CUSTOMER_REVIEW_APP"
;
case
DirectionalScreenName
.
preferentialHotList
:
return
"APP_SCREEN_PREFERENTIAL_HOT_LIST"
;
case
DirectionalScreenName
.
pointHistory
:
return
"APP_SCREEN_POINT_HISTORY"
;
case
DirectionalScreenName
.
refundHistory
:
return
"APP_SCREEN_REFUND_HISTORY"
;
case
DirectionalScreenName
.
home
:
return
"APP_SCREEN_HOME"
;
case
DirectionalScreenName
.
pointBack
:
return
"APP_SCREEN_POINTBACK"
;
case
DirectionalScreenName
.
brandList
:
return
"APP_SCREEN_BRAND_LIST"
;
case
DirectionalScreenName
.
news
:
return
"APP_SCREEN_NEWS"
;
case
DirectionalScreenName
.
brandLike
:
return
"APP_SCREEN_BRAND_LIKES"
;
case
DirectionalScreenName
.
productVoucher
:
return
"APP_SCREEN_PRODUCT_VOUCHER"
;
case
DirectionalScreenName
.
memberShip
:
return
"APP_SCREEN_MEMBERSHIP_LEVEL"
;
case
DirectionalScreenName
.
ranking
:
return
"APP_SCREEN_RANKING_PROGRAM"
;
case
DirectionalScreenName
.
mobileTopup
:
return
"APP_SCREEN_PRODUCT_MOBILE_TOPUP"
;
case
DirectionalScreenName
.
mobileTopupData
:
return
"APP_SCREEN_MOBILE_TOPUP_DATA"
;
case
DirectionalScreenName
.
topup
:
return
"APP_SCREEN_TOPUP"
;
case
DirectionalScreenName
.
register
:
return
"APP_SCREEN_REGISTER"
;
case
DirectionalScreenName
.
gifts
:
return
"APP_SCREEN_GIFTS"
;
case
DirectionalScreenName
.
viewSMS
:
return
"VIEW_SMS"
;
case
DirectionalScreenName
.
walkingCampaign
:
return
"APP_SCREEN_CAMPAIGN_WALKING"
;
case
DirectionalScreenName
.
applicationSetting
:
return
"APPLICATION_SETTING"
;
case
DirectionalScreenName
.
customerSupport
:
return
"APP_SCREEN_CUSTOMER_FEEDBACK"
;
case
DirectionalScreenName
.
historyInvitedFriend
:
return
"APP_SCREEN_HISTORY_INVITED"
;
case
DirectionalScreenName
.
gameWorldCup2022
:
return
"APP_SCREEN_GAME_WORLDCUP"
;
case
DirectionalScreenName
.
rateStorePopup
:
return
"OPEN_RATE_STORE"
;
case
DirectionalScreenName
.
simService
:
return
"APP_SCREEN_SIM_SERVICE"
;
case
DirectionalScreenName
.
vietlott
:
return
"APP_SCREEN_VIETLOTT"
;
case
DirectionalScreenName
.
shoppingOnline
:
return
"APP_SCREEN_SHOPPING_ONLINE"
;
case
DirectionalScreenName
.
electricBill
:
return
"APP_SCREEN_ELECTRIC_BILL"
;
case
DirectionalScreenName
.
partnerRedirect
:
return
"PARTNER_REDIRECT"
;
case
DirectionalScreenName
.
brandOffline
:
return
"VIEW_BRAND_TAB_VOUCHER_OFFLINE"
;
case
DirectionalScreenName
.
pipiScreen
:
return
"APP_SCREEN_PIPI"
;
case
DirectionalScreenName
.
campaignSevenDayScreen
:
return
"APP_SCREEN_CAMPAIGN_TASKS"
;
case
DirectionalScreenName
.
surveyCampaign
:
return
"APP_SCREEN_SURVERY_APP"
;
case
DirectionalScreenName
.
inviteFriend
:
return
"APP_SCREEN_INVITE_FRIEND"
;
case
DirectionalScreenName
.
viewVoucherWithCountTime
:
return
"APP_SCREEN_VIEW_VOUCHER"
;
case
DirectionalScreenName
.
viewAllVoucher
:
return
"APP_SCREEN_ALL_VOUCHER"
;
case
DirectionalScreenName
.
popViewController
:
return
"POP_VIEW_CONTROLLER"
;
case
DirectionalScreenName
.
finishScreen
:
return
"FINISHED_SCREEN"
;
case
DirectionalScreenName
.
screenAddInvitationCode
:
return
"APP_SCREEN_ADD_INVITATION_CODE"
;
case
DirectionalScreenName
.
luckyMoney
:
return
"APP_SCREEN_LUCKY_MONEY"
;
case
DirectionalScreenName
.
termPolicyDeleteAccount
:
return
"TERM_POLICY_DELETE_ACCOUNT"
;
case
DirectionalScreenName
.
privacyPolicy
:
return
"APP_SCREEN_PRIVACY_POLICY"
;
case
DirectionalScreenName
.
termsOfUse
:
return
"APP_SCREEN_TERMS_OF_USE"
;
case
DirectionalScreenName
.
termPolicyDecree13
:
return
"TERM_POLICY_DECREE_13"
;
case
DirectionalScreenName
.
bankAccountManager
:
return
"BANK_ACCOUNT_MANAGER"
;
case
DirectionalScreenName
.
familyMedon
:
return
"APP_SCREEN_CARD_FAMILY_MEDON"
;
case
DirectionalScreenName
.
familyMedonDetailCard
:
return
"MEDON_DETAIL_CARD"
;
case
DirectionalScreenName
.
familyHealthBook
:
return
"FAMILY_HEALTH_BOOK"
;
case
DirectionalScreenName
.
gameCenter
:
return
"VPLAY_GAME_CENTER"
;
case
DirectionalScreenName
.
vnTraPackage
:
return
"APP_SCREEN_VNTRA_PACKAGE"
;
case
DirectionalScreenName
.
myVnTraPackage
:
return
"APP_SCREEN_MY_VNTRA_PACKAGE"
;
case
DirectionalScreenName
.
detailTrafficService
:
return
"DETAIL_TRAFFIC_SERVICES"
;
case
DirectionalScreenName
.
makeDirectionScreen
:
return
"GET_DIRECTION_SCREEN"
;
case
DirectionalScreenName
.
webviewFullScreen
:
return
"APP_VIEW_WEBVIEW_FULL_SCREEN"
;
case
DirectionalScreenName
.
gamesBundle
:
return
"APP_SCREEN_GAME_BUNDLE"
;
case
DirectionalScreenName
.
gameCardDetail
:
return
"APP_SCREEN_GAME_CARD_DETAIL"
;
case
DirectionalScreenName
.
newInviteFriend
:
return
"APP_SCREEN_INVITE_FRIEND_MANAGER"
;
case
DirectionalScreenName
.
inviteFriendApply
:
return
"APP_SCREEN_INVITE_FRIEND_APPLY"
;
case
DirectionalScreenName
.
personal
:
return
"APP_SCREEN_PERSONAL"
;
case
DirectionalScreenName
.
voucherTab
:
return
"APP_SCREEN_VOUCHER_TAB"
;
case
DirectionalScreenName
.
introduction
:
return
"APP_SCREEN_INTRODUCTION"
;
case
DirectionalScreenName
.
listPaymentOfElectric
:
return
"APP_SCREEN_LIST_PAYMENT_OF_ELECTRIC"
;
case
DirectionalScreenName
.
favorite
:
return
"APP_SCREEN_CATEGORY_TAB_FAVORITE"
;
case
DirectionalScreenName
.
unknown
:
return
"UNKNOWN"
;
}
}
static
DirectionalScreenName
fromRawValue
(
String
rawValue
)
{
return
DirectionalScreenName
.
values
.
firstWhere
(
(
e
)
=>
e
.
rawValue
==
rawValue
,
orElse:
()
=>
DirectionalScreenName
.
unknown
,
);
}
static
fromString
(
String
s
)
{}
}
lib/directional/directional_screen.dart
View file @
75178f29
import
'package:flutter/cupertino.dart'
;
import
'package:get/get.dart'
;
import
'package:json_annotation/json_annotation.dart'
;
import
'../screen/pageDetail/campaign_detail_screen.dart'
;
import
'../shared/router_gage.dart'
;
import
'directional_action_type.dart'
;
part
'directional_screen.g.dart'
;
@JsonSerializable
()
class
DirectionalScreen
{
@JsonKey
(
name:
"click_action_type"
)
final
String
?
clickActionType
;
@JsonKey
(
name:
"click_action_param"
)
final
String
?
clickActionParam
;
final
ClickActionType
?
actionType
;
DirectionalScreen
({
this
.
clickActionType
,
this
.
clickActionParam
,
this
.
actionType
,
});
DirectionalScreen
({
this
.
clickActionType
,
this
.
clickActionParam
});
static
DirectionalScreen
?
build
({
String
?
clickActionType
,
String
?
clickActionParam
})
{
if
(
clickActionType
==
null
||
clickActionType
.
isEmpty
)
return
null
;
return
DirectionalScreen
(
clickActionType:
clickActionType
,
clickActionParam:
clickActionParam
);
}
factory
DirectionalScreen
.
fromJson
(
Map
<
String
,
dynamic
>
json
)
=>
_$DirectionalScreenFromJson
(
json
);
Map
<
String
,
dynamic
>
toJson
()
=>
_$DirectionalScreenToJson
(
this
);
void
begin
()
{
final
type
=
ClickActionTypeExtension
.
fromString
(
clickActionType
??
actionType
?.
key
??
""
);
@immutable
bool
begin
()
{
final
type
=
DirectionalScreenNameExtension
.
fromRawValue
(
clickActionType
??
""
);
if
(
type
==
null
)
{
print
(
"Không nhận diện được action type:
$clickActionType
"
);
return
;
return
false
;
}
switch
(
type
)
{
case
ClickActionType
.
campaignDetail
:
Get
.
to
(()
=>
const
CampaignDetailScreen
(),
arguments:
clickActionParam
);
break
;
case
DirectionalScreenName
.
setting
:
Get
.
toNamed
(
settingScreen
);
return
true
;
case
DirectionalScreenName
.
productOwnVoucher
:
Get
.
toNamed
(
voucherDetailScreen
,
arguments:
{
"customerProductId"
:
int
.
parse
(
clickActionParam
??
""
)});
return
true
;
default
:
print
(
"Không nhận diện được action type:
$clickActionType
"
);
return
false
;
}
}
}
lib/directional/directional_screen.g.dart
View file @
75178f29
...
...
@@ -10,19 +10,10 @@ DirectionalScreen _$DirectionalScreenFromJson(Map<String, dynamic> json) =>
DirectionalScreen
(
clickActionType:
json
[
'click_action_type'
]
as
String
?,
clickActionParam:
json
[
'click_action_param'
]
as
String
?,
actionType:
$enumDecodeNullable
(
_$ClickActionTypeEnumMap
,
json
[
'actionType'
],
),
);
Map
<
String
,
dynamic
>
_$DirectionalScreenToJson
(
DirectionalScreen
instance
)
=>
<
String
,
dynamic
>{
'click_action_type'
:
instance
.
clickActionType
,
'click_action_param'
:
instance
.
clickActionParam
,
'actionType'
:
_$ClickActionTypeEnumMap
[
instance
.
actionType
],
};
const
_$ClickActionTypeEnumMap
=
{
ClickActionType
.
campaignDetail
:
'campaignDetail'
,
};
lib/model/auth/working_site_model.dart
View file @
75178f29
import
'package:json_annotation/json_annotation.dart'
;
import
'package:mypoint_flutter_app/model/auth/customer_balance_model.dart'
;
import
'customer_balance_model.dart'
;
part
'working_site_model.g.dart'
;
@JsonSerializable
()
class
WorkingSiteModel
{
final
String
?
id
;
final
String
?
name
;
final
String
?
avatar
;
@JsonKey
(
name:
'customer_balance'
)
final
CustomerBalanceModel
?
customerBalanceModel
;
@JsonKey
(
name:
'primary_membership'
)
// final PrimaryMembership? primaryMembership;
WorkingSiteModel
({
this
.
id
,
this
.
name
,
this
.
avatar
,
this
.
customerBalanceModel
,
// this.primaryMembership,
});
factory
WorkingSiteModel
.
fromJson
(
Map
<
String
,
dynamic
>
json
)
=>
_$WorkingSiteModelFromJson
(
json
);
...
...
lib/model/auth/working_site_model.g.dart
View file @
75178f29
...
...
@@ -11,12 +11,6 @@ WorkingSiteModel _$WorkingSiteModelFromJson(Map<String, dynamic> json) =>
id:
json
[
'id'
]
as
String
?,
name:
json
[
'name'
]
as
String
?,
avatar:
json
[
'avatar'
]
as
String
?,
customerBalanceModel:
json
[
'customer_balance'
]
==
null
?
null
:
CustomerBalanceModel
.
fromJson
(
json
[
'customer_balance'
]
as
Map
<
String
,
dynamic
>,
),
);
Map
<
String
,
dynamic
>
_$WorkingSiteModelToJson
(
WorkingSiteModel
instance
)
=>
...
...
@@ -24,5 +18,4 @@ Map<String, dynamic> _$WorkingSiteModelToJson(WorkingSiteModel instance) =>
'id'
:
instance
.
id
,
'name'
:
instance
.
name
,
'avatar'
:
instance
.
avatar
,
'customer_balance'
:
instance
.
customerBalanceModel
,
};
lib/networking/restful_api_request.dart
View file @
75178f29
...
...
@@ -16,6 +16,7 @@ import '../preference/point/header_home_model.dart';
import
'../screen/faqs/faqs_model.dart'
;
import
'../screen/game/models/game_bundle_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_list_data_model.dart'
;
import
'../screen/onboarding/model/check_phone_response_model.dart'
;
import
'../screen/onboarding/model/onboarding_info_model.dart'
;
...
...
@@ -284,6 +285,11 @@ extension RestfullAPIClientAllApi on RestfulAPIClient {
return
requestNormal
(
path
,
Method
.
GET
,
{},
(
data
)
=>
ProductModel
.
fromJson
(
data
as
Json
));
}
Future
<
BaseResponseModel
<
ProductModel
>>
getCustomerProductDetail
(
int
id
)
async
{
final
path
=
APIPaths
.
getCustomerProductDetail
.
replaceAll
(
"%@"
,
id
.
toString
());
return
requestNormal
(
path
,
Method
.
GET
,
{},
(
data
)
=>
ProductModel
.
fromJson
(
data
as
Json
));
}
Future
<
BaseResponseModel
<
List
<
ProductStoreModel
>>>
getProductStores
(
int
id
)
async
{
final
body
=
{
"product_id"
:
id
,
"size"
:
20
,
"index"
:
0
};
return
requestNormal
(
APIPaths
.
getProductStores
,
Method
.
GET
,
body
,
(
data
)
{
...
...
@@ -398,7 +404,7 @@ extension RestfullAPIClientAllApi on RestfulAPIClient {
}
Future
<
BaseResponseModel
<
EmptyCodable
>>
deleteNotification
(
String
id
)
async
{
return
requestNormal
(
APIPaths
.
deleteNotification
,
Method
.
POST
,
{
"notification_id"
:
id
},
(
data
)
{
return
requestNormal
(
APIPaths
.
deleteNotification
,
Method
.
POST
,
{
"notification_id
__
"
:
id
},
(
data
)
{
return
EmptyCodable
.
fromJson
(
data
as
Json
);
});
}
...
...
@@ -419,6 +425,14 @@ extension RestfullAPIClientAllApi on RestfulAPIClient {
});
}
Future
<
BaseResponseModel
<
NotificationDetailResponseModel
>>
getNotificationDetail
(
String
id
)
async
{
String
?
token
=
DataPreference
.
instance
.
token
??
""
;
final
body
=
{
"notification_id"
:
id
,
"mark_as_seen"
:
"1"
,
"access_token"
:
token
};
return
requestNormal
(
APIPaths
.
notificationGetDetail
,
Method
.
POST
,
body
,
(
data
)
{
return
NotificationDetailResponseModel
.
fromJson
(
data
as
Json
);
});
}
Future
<
BaseResponseModel
<
TransactionHistoryModel
>>
getTransactionHistoryDetail
(
String
id
)
async
{
final
path
=
APIPaths
.
getTransactionHistoryDetail
.
replaceAll
(
"%@"
,
id
);
return
requestNormal
(
path
,
Method
.
GET
,
{},
(
data
)
{
...
...
lib/screen/notification/models/notification_detail_model.dart
0 → 100644
View file @
75178f29
import
'package:json_annotation/json_annotation.dart'
;
import
'package:mypoint_flutter_app/directional/directional_screen.dart'
;
import
'../../../model/auth/working_site_model.dart'
;
part
'notification_detail_model.g.dart'
;
@JsonSerializable
()
class
NotificationDetailModel
{
@JsonKey
(
name:
'notification_id'
)
final
String
?
notificationId
;
final
String
?
title
;
final
String
?
body
;
final
String
?
type
;
@JsonKey
(
name:
'click_action_type'
)
final
String
?
clickActionType
;
@JsonKey
(
name:
'click_action_param'
)
final
String
?
clickActionParam
;
@JsonKey
(
name:
'create_time'
)
final
String
?
createTime
;
@JsonKey
(
name:
'seen_at'
)
final
String
?
seenAt
;
@JsonKey
(
name:
'working_site'
)
final
WorkingSiteModel
?
workingSite
;
DirectionalScreen
?
get
directionalScreen
{
return
DirectionalScreen
.
build
(
clickActionType:
clickActionType
,
clickActionParam:
clickActionParam
,
);
}
NotificationDetailModel
({
this
.
notificationId
,
this
.
title
,
this
.
body
,
this
.
type
,
this
.
clickActionType
,
this
.
clickActionParam
,
this
.
createTime
,
this
.
seenAt
,
this
.
workingSite
,
});
factory
NotificationDetailModel
.
fromJson
(
Map
<
String
,
dynamic
>
json
)
=>
_$NotificationDetailModelFromJson
(
json
);
Map
<
String
,
dynamic
>
toJson
()
=>
_$NotificationDetailModelToJson
(
this
);
}
@JsonSerializable
()
class
NotificationDetailResponseModel
{
final
NotificationDetailModel
?
notification
;
NotificationDetailResponseModel
({
this
.
notification
});
factory
NotificationDetailResponseModel
.
fromJson
(
Map
<
String
,
dynamic
>
json
)
=>
_$NotificationDetailResponseModelFromJson
(
json
);
Map
<
String
,
dynamic
>
toJson
()
=>
_$NotificationDetailResponseModelToJson
(
this
);
}
\ No newline at end of file
lib/screen/notification/models/notification_detail_model.g.dart
0 → 100644
View file @
75178f29
// GENERATED CODE - DO NOT MODIFY BY HAND
part of
'notification_detail_model.dart'
;
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
NotificationDetailModel
_$NotificationDetailModelFromJson
(
Map
<
String
,
dynamic
>
json
,
)
=>
NotificationDetailModel
(
notificationId:
json
[
'notification_id'
]
as
String
?,
title:
json
[
'title'
]
as
String
?,
body:
json
[
'body'
]
as
String
?,
type:
json
[
'type'
]
as
String
?,
clickActionType:
json
[
'click_action_type'
]
as
String
?,
clickActionParam:
json
[
'click_action_param'
]
as
String
?,
createTime:
json
[
'create_time'
]
as
String
?,
seenAt:
json
[
'seen_at'
]
as
String
?,
workingSite:
json
[
'working_site'
]
==
null
?
null
:
WorkingSiteModel
.
fromJson
(
json
[
'working_site'
]
as
Map
<
String
,
dynamic
>,
),
);
Map
<
String
,
dynamic
>
_$NotificationDetailModelToJson
(
NotificationDetailModel
instance
,
)
=>
<
String
,
dynamic
>{
'notification_id'
:
instance
.
notificationId
,
'title'
:
instance
.
title
,
'body'
:
instance
.
body
,
'type'
:
instance
.
type
,
'click_action_type'
:
instance
.
clickActionType
,
'click_action_param'
:
instance
.
clickActionParam
,
'create_time'
:
instance
.
createTime
,
'seen_at'
:
instance
.
seenAt
,
'working_site'
:
instance
.
workingSite
,
};
NotificationDetailResponseModel
_$NotificationDetailResponseModelFromJson
(
Map
<
String
,
dynamic
>
json
,
)
=>
NotificationDetailResponseModel
(
notification:
json
[
'notification'
]
==
null
?
null
:
NotificationDetailModel
.
fromJson
(
json
[
'notification'
]
as
Map
<
String
,
dynamic
>,
),
);
Map
<
String
,
dynamic
>
_$NotificationDetailResponseModelToJson
(
NotificationDetailResponseModel
instance
,
)
=>
<
String
,
dynamic
>{
'notification'
:
instance
.
notification
};
lib/screen/notification/models/notification_item_model.dart
View file @
75178f29
import
'package:json_annotation/json_annotation.dart'
;
import
'../../../directional/directional_screen.dart'
;
part
'notification_item_model.g.dart'
;
@JsonSerializable
()
class
NotificationItemModel
{
...
...
@@ -22,6 +24,13 @@ class NotificationItemModel {
bool
get
hasSeen
=>
(
seenAt
??
""
).
isNotEmpty
;
DirectionalScreen
?
get
directionalScreen
{
return
DirectionalScreen
.
build
(
clickActionType:
clickActionType
,
clickActionParam:
clickActionParam
,
);
}
NotificationItemModel
({
this
.
notificationId
,
this
.
title
,
...
...
lib/screen/notification/notification_detail_screen.dart
0 → 100644
View file @
75178f29
import
'package:flutter/material.dart'
;
import
'package:mypoint_flutter_app/widgets/custom_app_bar.dart'
;
import
'../../widgets/image_loader.dart'
;
import
'models/notification_detail_model.dart'
;
class
NotificationDetailScreen
extends
StatelessWidget
{
final
NotificationDetailModel
notification
;
const
NotificationDetailScreen
({
super
.
key
,
required
this
.
notification
});
@override
Widget
build
(
BuildContext
context
)
{
return
Scaffold
(
appBar:
CustomAppBar
.
back
(
title:
"Chi tiết thông báo"
),
body:
Container
(
color:
Colors
.
grey
.
shade100
,
padding:
const
EdgeInsets
.
all
(
16
),
child:
IntrinsicHeight
(
child:
Container
(
padding:
const
EdgeInsets
.
all
(
16
),
decoration:
BoxDecoration
(
color:
Colors
.
white
,
borderRadius:
BorderRadius
.
circular
(
12
)),
child:
Row
(
crossAxisAlignment:
CrossAxisAlignment
.
start
,
children:
[
ClipRRect
(
borderRadius:
BorderRadius
.
circular
(
8
),
child:
loadNetworkImage
(
url:
notification
.
workingSite
?.
avatar
??
""
,
fit:
BoxFit
.
cover
,
width:
40
,
height:
40
,
placeholderAsset:
'assets/images/ic_logo.png'
,
),
),
const
SizedBox
(
width:
12
),
Expanded
(
child:
Column
(
crossAxisAlignment:
CrossAxisAlignment
.
start
,
children:
[
Text
(
notification
.
title
??
''
,
style:
const
TextStyle
(
fontWeight:
FontWeight
.
bold
,
fontSize:
16
)),
const
SizedBox
(
height:
6
),
Text
(
notification
.
body
??
''
,
style:
const
TextStyle
(
fontSize:
14
)),
const
SizedBox
(
height:
10
),
Text
(
_timeAgo
(
notification
.
createTime
),
style:
const
TextStyle
(
color:
Colors
.
grey
,
fontSize:
13
)),
],
),
),
],
),
),
),
),
);
}
String
_timeAgo
(
String
?
dateStr
)
{
if
(
dateStr
==
null
)
return
''
;
final
time
=
DateTime
.
tryParse
(
dateStr
);
if
(
time
==
null
)
return
''
;
final
now
=
DateTime
.
now
();
final
diff
=
now
.
difference
(
time
);
if
(
diff
.
inDays
>
0
)
return
'
${diff.inDays}
ngày trước'
;
if
(
diff
.
inHours
>
0
)
return
'
${diff.inHours}
giờ trước'
;
if
(
diff
.
inMinutes
>
0
)
return
'
${diff.inMinutes}
phút trước'
;
return
'Vừa xong'
;
}
}
lib/screen/notification/notification_screen.dart
View file @
75178f29
...
...
@@ -34,6 +34,11 @@ class _NotificationScreenState extends BaseState<NotificationScreen> with BasicS
_viewModel
.
fetchNotifications
(
refresh:
false
);
}
});
_viewModel
.
onShowAlertError
=
(
message
)
{
if
(
message
.
isNotEmpty
)
{
showAlertError
(
content:
message
);
}
};
}
@override
...
...
@@ -166,11 +171,11 @@ class _NotificationScreenState extends BaseState<NotificationScreen> with BasicS
_confirmDeleteAllNotifications
()
{
final
dataAlert
=
DataAlertModel
(
title:
"
Quên mật khẩu
"
,
description:
"Bạn c
ần đăng xuất khỏi tài khoản này để đặt lại mật khẩu. Bạn chắc chứ?.
"
,
title:
"
Xoá tất cả
"
,
description:
"Bạn c
ó muốn xoá hết tất cả thông báo không?
\n
Lưu ý: bạn sẽ không thể xem lại thông báo đã xoá
"
,
localHeaderImage:
"assets/images/ic_pipi_03.png"
,
buttons:
[
AlertButton
(
text:
"
Đồng ý
"
,
text:
"
Xoá
"
,
onPressed:
()
{
Get
.
back
();
_viewModel
.
deleteAllNotifications
();
...
...
@@ -258,7 +263,26 @@ class _NotificationScreenState extends BaseState<NotificationScreen> with BasicS
}
Widget
_buildNotificationItem
(
NotificationItemModel
item
)
{
return
Container
(
return
Dismissible
(
key:
ValueKey
(
item
.
notificationId
??
item
.
createTime
),
direction:
DismissDirection
.
endToStart
,
background:
Container
(
alignment:
Alignment
.
centerRight
,
padding:
const
EdgeInsets
.
symmetric
(
horizontal:
20
),
color:
Colors
.
red
,
child:
const
Icon
(
Icons
.
delete
,
color:
Colors
.
white
),
),
onDismissed:
(
direction
)
{
_viewModel
.
handleRemoveNotification
(
item
);
// _viewModel.notifications.remove(item);
},
child:
GestureDetector
(
onTap:
()
{
print
(
"Click item
${item.title}
"
);
_viewModel
.
handleClickNotification
(
item
);
// item.directionalScreen?.begin();
},
child:
Container
(
margin:
const
EdgeInsets
.
only
(
bottom:
12
),
padding:
const
EdgeInsets
.
all
(
12
),
decoration:
BoxDecoration
(
...
...
@@ -298,6 +322,8 @@ class _NotificationScreenState extends BaseState<NotificationScreen> with BasicS
),
],
),
),
),
);
}
}
lib/screen/notification/notification_viewmodel.dart
View file @
75178f29
import
'package:get/get.dart'
;
import
'package:mypoint_flutter_app/configs/constants.dart'
;
import
'package:mypoint_flutter_app/networking/restful_api_request.dart'
;
import
'../../base/restful_api_viewmodel.dart'
;
import
'../../preference/data_preference.dart'
;
import
'models/category_notify_item_model.dart'
;
import
'models/notification_item_model.dart'
;
import
'notification_detail_screen.dart'
;
class
NotificationViewModel
extends
RestfulApiViewModel
{
var
categories
=
RxList
<
CategoryNotifyItemModel
>();
var
notifications
=
RxList
<
NotificationItemModel
>();
final
RxBool
isLoading
=
false
.
obs
;
final
_pageLimit
=
10
;
var
_notificationIndex
=
0
;
void
Function
(
String
message
)?
onShowAlertError
;
var
_hasMoreData
=
true
;
CategoryNotifyItemModel
?
get
selectedCategory
=>
categories
.
isNotEmpty
?
categories
.
firstWhere
((
item
)
=>
item
.
isSelected
??
false
)
:
null
;
...
...
@@ -33,22 +39,29 @@ class NotificationViewModel extends RestfulApiViewModel {
void
fetchNotifications
({
bool
refresh
=
false
})
async
{
if
(
isLoading
.
value
)
return
;
if
(!
refresh
&&
!
_hasMoreData
)
{
return
;
}
if
(
refresh
)
{
_notificationIndex
=
0
;
}
isLoading
.
value
=
true
;
String
?
token
=
DataPreference
.
instance
.
token
??
""
;
final
body
=
{
"access_token"
:
token
,
"start"
:
refresh
?
0
:
notification
s
.
length
,
"limit"
:
10
,
"start"
:
_
notification
Index
,
"limit"
:
_pageLimit
,
"noti_group_id"
:
selectedCategory
?.
id
??
""
,
};
client
.
getNotifications
(
body
).
then
((
value
)
{
isLoading
.
value
=
false
;
hideLoading
();
final
items
=
value
.
data
?.
items
??
[];
if
(
refresh
)
{
notifications
.
value
=
value
.
data
?.
items
??
[]
;
notifications
.
value
=
items
;
}
else
{
notifications
.
addAll
(
value
.
data
?.
items
??
[]
);
notifications
.
addAll
(
items
);
}
_notificationIndex
+=
items
.
length
;
_hasMoreData
=
(
value
.
data
?.
items
?.
length
??
0
)
==
_pageLimit
;
});
}
...
...
@@ -70,4 +83,28 @@ class NotificationViewModel extends RestfulApiViewModel {
_fetchCategories
();
});
}
handleRemoveNotification
(
NotificationItemModel
item
)
{
if
(
item
.
notificationId
==
null
)
{
return
;
}
client
.
deleteNotification
(
item
.
notificationId
??
""
).
then
((
value
)
{
notifications
.
remove
(
item
);
if
(
notifications
.
length
<=
_pageLimit
)
{
fetchNotifications
(
refresh:
false
);
}
});
}
handleClickNotification
(
NotificationItemModel
item
)
{
showLoading
();
client
.
getNotificationDetail
(
item
.
notificationId
??
""
).
then
((
value
)
{
hideLoading
();
if
(!
value
.
isSuccess
)
return
;
final
notification
=
value
.
data
?.
notification
;
if
(
notification
==
null
)
return
;
final
pushSuccess
=
notification
.
directionalScreen
?.
begin
()
??
false
;
if
(!
pushSuccess
)
{
Get
.
to
(()
=>
NotificationDetailScreen
(
notification:
notification
));
}
});
}
}
lib/screen/voucher/detail/store_list_section.dart
View file @
75178f29
import
'package:flutter/material.dart'
;
import
'package:get/get_state_manager/src/rx_flutter/rx_obx_widget.dart'
;
import
'package:mypoint_flutter_app/shared/direction_google_map.dart'
;
import
'../models/product_store_model.dart'
;
...
...
@@ -11,10 +12,10 @@ class StoreListSection extends StatelessWidget {
@override
Widget
build
(
BuildContext
context
)
{
return
Obx
(()
{
if
(
stores
.
isEmpty
)
{
return
const
SizedBox
.
shrink
();
}
return
Container
(
margin:
const
EdgeInsets
.
symmetric
(
horizontal:
16
,
vertical:
8
),
padding:
const
EdgeInsets
.
all
(
16
),
...
...
@@ -24,16 +25,18 @@ class StoreListSection extends StatelessWidget {
children:
[
const
Text
(
'Địa điểm áp dụng:'
,
style:
TextStyle
(
fontWeight:
FontWeight
.
bold
,
fontSize:
16
)),
const
SizedBox
(
height:
10
),
//
...stores.map(
(store) => _buildStoreItem(store)).toList(),
...
stores
.
map
(
(
store
)
=>
InkWell
(
...
stores
.
map
(
(
store
)
=>
InkWell
(
onTap:
()
{
_onTapStore
(
store
);
},
child:
_buildStoreItem
(
store
),
)),
),
),
],
),
);
});
}
_onTapStore
(
ProductStoreModel
store
)
{
...
...
lib/screen/voucher/detail/voucher_detail_screen.dart
View file @
75178f29
...
...
@@ -4,6 +4,7 @@ import 'package:flutter_widget_from_html/flutter_widget_from_html.dart';
import
'package:mypoint_flutter_app/extensions/num_extension.dart'
;
import
'package:mypoint_flutter_app/screen/voucher/detail/store_list_section.dart'
;
import
'package:mypoint_flutter_app/screen/voucher/models/product_type.dart'
;
import
'package:mypoint_flutter_app/screen/voucher/voucher_code_card_screen.dart'
;
import
'package:url_launcher/url_launcher.dart'
;
import
'../../../base/base_screen.dart'
;
import
'../../../base/basic_state.dart'
;
...
...
@@ -31,20 +32,31 @@ class VoucherDetailScreen extends BaseScreen {
}
class
_VoucherDetailScreenState
extends
BaseState
<
VoucherDetailScreen
>
with
BasicState
{
late
final
int
productId
;
late
final
VoucherDetailViewModel
_viewModel
;
double
_infoHeight
=
0
;
@override
void
initState
()
{
super
.
initState
();
int
?
productId
;
int
?
customerProductId
;
final
args
=
Get
.
arguments
;
if
(
args
is
int
)
{
productId
=
args
;
}
else
if
(
args
is
Map
)
{
if
(
args
is
Map
)
{
productId
=
args
[
'productId'
];
customerProductId
=
args
[
'customerProductId'
];
}
if
(
productId
==
null
&&
customerProductId
==
null
)
{
WidgetsBinding
.
instance
.
addPostFrameCallback
((
_
)
{
Get
.
back
();
});
return
;
}
_viewModel
=
Get
.
put
(
VoucherDetailViewModel
(
productId:
productId
));
_viewModel
=
Get
.
put
(
VoucherDetailViewModel
(
productId:
productId
,
customerProductId:
customerProductId
,
));
_viewModel
.
onShowAlertError
=
(
message
)
{
if
(
message
.
isNotEmpty
)
{
showAlertError
(
content:
message
);
...
...
@@ -207,7 +219,7 @@ class _VoucherDetailScreenState extends BaseState<VoucherDetailScreen> with Basi
product
.
expired
?
"Hết hạn"
:
product
.
expire
,
style:
const
TextStyle
(
color:
BaseColor
.
primary500
,
fontWeight:
FontWeight
.
bold
,
fontSize:
12
),
),
if
(
isOutOfStock
)
if
(
isOutOfStock
&&
!
_viewModel
.
isMyProduct
)
Container
(
margin:
const
EdgeInsets
.
only
(
left:
8
),
padding:
const
EdgeInsets
.
symmetric
(
horizontal:
12
,
vertical:
4
),
...
...
@@ -315,9 +327,6 @@ class _VoucherDetailScreenState extends BaseState<VoucherDetailScreen> with Basi
Widget
_buildBottomAction
(
ProductModel
product
)
{
final
bool
isOutOfStock
=
!(
product
.
inStock
??
true
);
if
(
isOutOfStock
)
{
return
const
SizedBox
.
shrink
();
}
if
(
product
.
isMyProduct
&&
product
.
customerInfoModel
?.
status
!=
MyProductStatusType
.
waiting
)
{
return
const
SizedBox
.
shrink
();
}
...
...
@@ -326,6 +335,8 @@ class _VoucherDetailScreenState extends BaseState<VoucherDetailScreen> with Basi
}
if
(
product
.
isMyProduct
)
{
return
_buildUseButton
();
}
else
if
(
isOutOfStock
)
{
return
const
SizedBox
.
shrink
();
}
else
if
(
product
.
price
?.
method
==
CashType
.
point
)
{
return
_buildExchangeButton
();
}
else
{
...
...
@@ -351,7 +362,8 @@ class _VoucherDetailScreenState extends BaseState<VoucherDetailScreen> with Basi
height:
48
,
child:
ElevatedButton
(
onPressed:
()
{
// TODO: Handle sử dụng voucher
if
(
_viewModel
.
product
.
value
==
null
)
return
;
Get
.
to
(()
=>
VoucherCodeCardScreen
(
product:
_viewModel
.
product
.
value
!,));
},
style:
ElevatedButton
.
styleFrom
(
backgroundColor:
Colors
.
green
,
...
...
@@ -475,9 +487,11 @@ class _VoucherDetailScreenState extends BaseState<VoucherDetailScreen> with Basi
}
final
dataAlert
=
DataAlertModel
(
title:
"Xác nhận"
,
description:
"Bạn có muốn sử dụng <b style=
\"
color:#E71D28
\"
>
${amountToBePaid.money(CurrencyUnit.point)}
</b> MyPoint để đổi Ưu Đãi này không?"
,
description:
"Bạn có muốn sử dụng <b style=
\"
color:#E71D28
\"
>
${amountToBePaid.money(CurrencyUnit.point)}
</b> MyPoint để đổi Ưu Đãi này không?"
,
localHeaderImage:
"assets/images/ic_pipi_02.png"
,
buttons:
[
AlertButton
(
buttons:
[
AlertButton
(
text:
"Đồng ý"
,
onPressed:
()
{
Get
.
back
();
...
...
@@ -486,12 +500,8 @@ class _VoucherDetailScreenState extends BaseState<VoucherDetailScreen> with Basi
bgColor:
BaseColor
.
primary500
,
textColor:
Colors
.
white
,
),
AlertButton
(
text:
"Huỷ"
,
onPressed:
()
=>
Get
.
back
(),
bgColor:
Colors
.
white
,
textColor:
BaseColor
.
second500
,
),],
AlertButton
(
text:
"Huỷ"
,
onPressed:
()
=>
Get
.
back
(),
bgColor:
Colors
.
white
,
textColor:
BaseColor
.
second500
),
],
);
showAlert
(
data:
dataAlert
);
}
...
...
lib/screen/voucher/detail/voucher_detail_viewmodel.dart
View file @
75178f29
...
...
@@ -10,14 +10,21 @@ import '../models/product_model.dart';
import
'../models/product_store_model.dart'
;
class
VoucherDetailViewModel
extends
RestfulApiViewModel
{
final
int
productId
;
VoucherDetailViewModel
({
required
this
.
productId
});
final
int
?
productId
;
final
int
?
customerProductId
;
VoucherDetailViewModel
({
this
.
productId
,
this
.
customerProductId
,
});
var
stores
=
RxList
<
ProductStoreModel
>();
var
product
=
Rxn
<
ProductModel
>();
var
isLoading
=
false
.
obs
;
var
liked
=
false
.
obs
;
void
Function
(
String
message
)?
onShowAlertError
;
var
quantity
=
1
.
obs
;
bool
get
isMyProduct
=>
customerProductId
!=
null
;
int
?
get
_id
=>
productId
??
product
.
value
?.
id
;
@override
void
onInit
()
{
...
...
@@ -27,6 +34,7 @@ class VoucherDetailViewModel extends RestfulApiViewModel {
}
Future
<
void
>
toggleFavorite
()
async
{
if
(
_id
==
null
)
return
;
final
value
=
product
.
value
;
if
(
value
==
null
)
return
;
try
{
...
...
@@ -35,7 +43,7 @@ class VoucherDetailViewModel extends RestfulApiViewModel {
value
?.
likeId
=
0
;
liked
.
value
=
false
;
}
else
{
final
response
=
await
client
.
likeProduct
(
productId
);
final
response
=
await
client
.
likeProduct
(
_id
!
);
value
?.
likeId
=
response
.
data
?.
id
;
liked
.
value
=
(
response
.
data
?.
id
??
0
)
!=
0
;
}
...
...
@@ -48,20 +56,25 @@ class VoucherDetailViewModel extends RestfulApiViewModel {
if
(
isLoading
.
value
)
return
;
try
{
isLoading
.
value
=
true
;
final
response
=
await
client
.
getProduct
(
productId
);
final
response
=
isMyProduct
?
await
client
.
getCustomerProductDetail
(
customerProductId
??
0
)
:
await
client
.
getProduct
(
productId
??
0
);
product
.
value
=
response
.
data
;
liked
.
value
=
product
.
value
?.
liked
==
true
;
}
catch
(
error
)
{
onShowAlertError
?.
call
(
"Error fetching product detail:
$error
"
);
}
finally
{
isLoading
.
value
=
false
;
if
(
isMyProduct
)
{
_getProductStores
();
}
}
}
Future
<
void
>
_getProductStores
()
async
{
if
(
_id
==
null
)
return
;
try
{
final
response
=
await
client
.
getProductStores
(
productId
);
final
response
=
await
client
.
getProductStores
(
_id
!
);
stores
.
value
=
response
.
data
??
[];
stores
.
refresh
();
}
catch
(
error
)
{
onShowAlertError
?.
call
(
"Error product stores:
$error
"
);
print
(
"Error product stores:
$error
"
);
...
...
lib/screen/voucher/models/product_model.dart
View file @
75178f29
...
...
@@ -33,7 +33,7 @@ class ProductModel {
@JsonKey
(
name:
'customer_product_info'
)
final
ProductCustomerInfoModel
?
customerInfoModel
;
@JsonKey
(
name:
'product_item'
)
final
ProductItemModel
?
item
Model
;
final
ProductItemModel
?
item
;
@JsonKey
(
name:
'expire_time'
)
final
String
?
expireTime
;
@JsonKey
(
name:
'require_form_regis'
)
...
...
@@ -51,7 +51,7 @@ class ProductModel {
this
.
media
,
this
.
previewFlashSale
,
this
.
customerInfoModel
,
this
.
item
Model
,
this
.
item
,
this
.
expireTime
,
this
.
requireFormRegis
,
this
.
type
,
...
...
@@ -66,7 +66,7 @@ class ProductModel {
}
String
get
expire
{
final
ex
=
(
isMyProduct
?
item
Model
?.
expireTime
:
expireTime
)
??
""
;
final
ex
=
(
isMyProduct
?
item
?.
expireTime
:
expireTime
)
??
""
;
return
ex
.
toDate
()?.
toFormattedString
()
??
""
;
}
...
...
lib/screen/voucher/models/product_model.g.dart
View file @
75178f29
...
...
@@ -46,7 +46,7 @@ ProductModel _$ProductModelFromJson(Map<String, dynamic> json) => ProductModel(
:
ProductCustomerInfoModel
.
fromJson
(
json
[
'customer_product_info'
]
as
Map
<
String
,
dynamic
>,
),
item
Model
:
item:
json
[
'product_item'
]
==
null
?
null
:
ProductItemModel
.
fromJson
(
...
...
@@ -69,7 +69,7 @@ Map<String, dynamic> _$ProductModelToJson(ProductModel instance) =>
'media'
:
instance
.
media
,
'preview_campaign_flash_sale'
:
instance
.
previewFlashSale
,
'customer_product_info'
:
instance
.
customerInfoModel
,
'product_item'
:
instance
.
item
Model
,
'product_item'
:
instance
.
item
,
'expire_time'
:
instance
.
expireTime
,
'require_form_regis'
:
instance
.
requireFormRegis
,
'type'
:
instance
.
type
,
...
...
lib/screen/voucher/sub_widget/voucher_item_grid.dart
View file @
75178f29
...
...
@@ -27,7 +27,7 @@ class VoucherItemGrid extends StatelessWidget {
final
product
=
items
[
index
];
return
GestureDetector
(
onTap:
()
{
Get
.
toNamed
(
voucherDetailScreen
,
arguments:
product
.
id
);
Get
.
toNamed
(
voucherDetailScreen
,
arguments:
{
"productId"
:
product
.
id
}
);
},
child:
_VoucherGridItem
(
product:
product
,
...
...
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