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
8bef97c9
Commit
8bef97c9
authored
May 16, 2025
by
DatHV
Browse files
update payment detail
parent
7777aa65
Changes
32
Hide whitespace changes
Inline
Side-by-side
lib/screen/transaction/model/payment_method_type.dart
0 → 100644
View file @
8bef97c9
enum
PaymentMethodType
{
card
,
wallet
,
transfer
,
internalCard
;
factory
PaymentMethodType
.
fromString
(
String
value
)
{
switch
(
value
)
{
case
'CARD'
:
return
PaymentMethodType
.
card
;
case
'WALLET'
:
return
PaymentMethodType
.
wallet
;
case
'VA_QRCODE'
:
return
PaymentMethodType
.
transfer
;
case
'INTERNATIONAL_CARD'
:
return
PaymentMethodType
.
internalCard
;
default
:
throw
ArgumentError
(
'Unknown PaymentMethodType:
$value
'
);
}
}
String
get
methodBillEVN
{
switch
(
this
)
{
case
PaymentMethodType
.
card
:
return
'DomesticATM'
;
case
PaymentMethodType
.
wallet
:
return
'VitapayWallet'
;
case
PaymentMethodType
.
transfer
:
return
'VA_QRCODE'
;
case
PaymentMethodType
.
internalCard
:
return
'INTERNATIONAL_CARD'
;
}
}
}
lib/screen/transaction/model/preview_order_payment_model.dart
0 → 100644
View file @
8bef97c9
import
'dart:core'
;
import
'package:json_annotation/json_annotation.dart'
;
import
'package:mypoint_flutter_app/screen/transaction/model/preview_order_payment_point_data_model.dart'
;
import
'package:mypoint_flutter_app/screen/transaction/model/preview_order_product_info_model.dart'
;
part
'preview_order_payment_model.g.dart'
;
@JsonSerializable
()
class
PreviewOrderPaymentModel
{
@JsonKey
(
name:
'total_cash_coupon'
)
final
int
?
totalCashCoupon
;
@JsonKey
(
name:
'fees_price'
)
final
int
?
feesPrice
;
@JsonKey
(
name:
'total_cash'
)
final
int
?
totalCash
;
@JsonKey
(
name:
'fee_note'
)
final
String
?
feeNote
;
@JsonKey
(
name:
'point_data'
)
final
PreviewOrderPaymentPointDataModel
?
pointData
;
@JsonKey
(
name:
'product_info'
)
final
List
<
PreviewOrderProductInfoModel
>?
productInfo
;
@JsonKey
(
name:
'total_price'
)
final
int
?
totalPrice
;
@JsonKey
(
name:
'discount_coupon_value'
)
final
int
?
discountCouponValue
;
@JsonKey
(
name:
'payment_method'
)
final
String
?
paymentMethod
;
@JsonKey
(
name:
'product_type'
)
final
String
?
productType
;
PreviewOrderPaymentModel
({
this
.
totalCashCoupon
,
this
.
feesPrice
,
this
.
totalCash
,
this
.
feeNote
,
this
.
pointData
,
this
.
productInfo
,
this
.
totalPrice
,
this
.
discountCouponValue
,
this
.
paymentMethod
,
this
.
productType
,
});
factory
PreviewOrderPaymentModel
.
fromJson
(
Map
<
String
,
dynamic
>
json
)
=>
_$PreviewOrderPaymentModelFromJson
(
json
);
Map
<
String
,
dynamic
>
toJson
()
=>
_$PreviewOrderPaymentModelToJson
(
this
);
}
lib/screen/transaction/model/preview_order_payment_model.g.dart
0 → 100644
View file @
8bef97c9
// GENERATED CODE - DO NOT MODIFY BY HAND
part of
'preview_order_payment_model.dart'
;
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
PreviewOrderPaymentModel
_$PreviewOrderPaymentModelFromJson
(
Map
<
String
,
dynamic
>
json
,
)
=>
PreviewOrderPaymentModel
(
totalCashCoupon:
(
json
[
'total_cash_coupon'
]
as
num
?)?.
toInt
(),
feesPrice:
(
json
[
'fees_price'
]
as
num
?)?.
toInt
(),
totalCash:
(
json
[
'total_cash'
]
as
num
?)?.
toInt
(),
feeNote:
json
[
'fee_note'
]
as
String
?,
pointData:
json
[
'point_data'
]
==
null
?
null
:
PreviewOrderPaymentPointDataModel
.
fromJson
(
json
[
'point_data'
]
as
Map
<
String
,
dynamic
>,
),
productInfo:
(
json
[
'product_info'
]
as
List
<
dynamic
>?)
?.
map
(
(
e
)
=>
PreviewOrderProductInfoModel
.
fromJson
(
e
as
Map
<
String
,
dynamic
>,
),
)
.
toList
(),
totalPrice:
(
json
[
'total_price'
]
as
num
?)?.
toInt
(),
discountCouponValue:
(
json
[
'discount_coupon_value'
]
as
num
?)?.
toInt
(),
paymentMethod:
json
[
'payment_method'
]
as
String
?,
productType:
json
[
'product_type'
]
as
String
?,
);
Map
<
String
,
dynamic
>
_$PreviewOrderPaymentModelToJson
(
PreviewOrderPaymentModel
instance
,
)
=>
<
String
,
dynamic
>{
'total_cash_coupon'
:
instance
.
totalCashCoupon
,
'fees_price'
:
instance
.
feesPrice
,
'total_cash'
:
instance
.
totalCash
,
'fee_note'
:
instance
.
feeNote
,
'point_data'
:
instance
.
pointData
,
'product_info'
:
instance
.
productInfo
,
'total_price'
:
instance
.
totalPrice
,
'discount_coupon_value'
:
instance
.
discountCouponValue
,
'payment_method'
:
instance
.
paymentMethod
,
'product_type'
:
instance
.
productType
,
};
lib/screen/transaction/model/preview_order_payment_point_data_model.dart
0 → 100644
View file @
8bef97c9
import
'package:json_annotation/json_annotation.dart'
;
part
'preview_order_payment_point_data_model.g.dart'
;
@JsonSerializable
()
class
PreviewOrderPaymentPointDataModel
{
final
int
?
status
;
final
int
?
point
;
@JsonKey
(
name:
'text_display'
)
final
String
?
textDisplay
;
PreviewOrderPaymentPointDataModel
({
this
.
status
,
this
.
point
,
this
.
textDisplay
,
});
factory
PreviewOrderPaymentPointDataModel
.
fromJson
(
Map
<
String
,
dynamic
>
json
)
=>
_$PreviewOrderPaymentPointDataModelFromJson
(
json
);
Map
<
String
,
dynamic
>
toJson
()
=>
_$PreviewOrderPaymentPointDataModelToJson
(
this
);
}
\ No newline at end of file
lib/screen/transaction/model/preview_order_payment_point_data_model.g.dart
0 → 100644
View file @
8bef97c9
// GENERATED CODE - DO NOT MODIFY BY HAND
part of
'preview_order_payment_point_data_model.dart'
;
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
PreviewOrderPaymentPointDataModel
_$PreviewOrderPaymentPointDataModelFromJson
(
Map
<
String
,
dynamic
>
json
,
)
=>
PreviewOrderPaymentPointDataModel
(
status:
(
json
[
'status'
]
as
num
?)?.
toInt
(),
point:
(
json
[
'point'
]
as
num
?)?.
toInt
(),
textDisplay:
json
[
'text_display'
]
as
String
?,
);
Map
<
String
,
dynamic
>
_$PreviewOrderPaymentPointDataModelToJson
(
PreviewOrderPaymentPointDataModel
instance
,
)
=>
<
String
,
dynamic
>{
'status'
:
instance
.
status
,
'point'
:
instance
.
point
,
'text_display'
:
instance
.
textDisplay
,
};
lib/screen/transaction/model/preview_order_product_info_model.dart
0 → 100644
View file @
8bef97c9
import
'package:json_annotation/json_annotation.dart'
;
part
'preview_order_product_info_model.g.dart'
;
@JsonSerializable
()
class
PreviewOrderProductInfoModel
{
final
String
?
name
;
final
String
?
value
;
PreviewOrderProductInfoModel
({
this
.
name
,
this
.
value
,
});
factory
PreviewOrderProductInfoModel
.
fromJson
(
Map
<
String
,
dynamic
>
json
)
=>
_$PreviewOrderProductInfoModelFromJson
(
json
);
Map
<
String
,
dynamic
>
toJson
()
=>
_$PreviewOrderProductInfoModelToJson
(
this
);
}
\ No newline at end of file
lib/screen/transaction/model/preview_order_product_info_model.g.dart
0 → 100644
View file @
8bef97c9
// GENERATED CODE - DO NOT MODIFY BY HAND
part of
'preview_order_product_info_model.dart'
;
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
PreviewOrderProductInfoModel
_$PreviewOrderProductInfoModelFromJson
(
Map
<
String
,
dynamic
>
json
,
)
=>
PreviewOrderProductInfoModel
(
name:
json
[
'name'
]
as
String
?,
value:
json
[
'value'
]
as
String
?,
);
Map
<
String
,
dynamic
>
_$PreviewOrderProductInfoModelToJson
(
PreviewOrderProductInfoModel
instance
,
)
=>
<
String
,
dynamic
>{
'name'
:
instance
.
name
,
'value'
:
instance
.
value
};
lib/screen/transaction/transaction_detail_screen.dart
0 → 100644
View file @
8bef97c9
import
'package:flutter/material.dart'
;
import
'package:flutter/cupertino.dart'
;
import
'package:get/get.dart'
;
import
'package:cached_network_image/cached_network_image.dart'
;
import
'package:intl/intl.dart'
;
import
'../../widgets/custom_app_bar.dart'
;
import
'../../widgets/dashed_line.dart'
;
import
'model/payment_bank_account_info_model.dart'
;
import
'model/payment_method_model.dart'
;
import
'model/preview_order_payment_model.dart'
;
import
'model/preview_order_payment_point_data_model.dart'
;
import
'transaction_detail_viewmodel.dart'
;
class
TransactionDetailScreen
extends
StatefulWidget
{
const
TransactionDetailScreen
({
super
.
key
});
@override
State
<
TransactionDetailScreen
>
createState
()
=>
_TransactionDetailScreenState
();
}
class
_TransactionDetailScreenState
extends
State
<
TransactionDetailScreen
>
{
final
TransactionDetailViewModel
viewModel
=
Get
.
put
(
TransactionDetailViewModel
());
final
currencyFormatter
=
NumberFormat
.
currency
(
locale:
'vi_VN'
,
symbol:
'đ'
,
decimalDigits:
0
,
);
bool
usePoints
=
true
;
int
selectedPaymentMethodIndex
=
-
1
;
bool
isPaymentMethodsExpanded
=
true
;
@override
void
initState
()
{
super
.
initState
();
viewModel
.
refreshData
();
}
@override
Widget
build
(
BuildContext
context
)
{
return
Scaffold
(
backgroundColor:
Colors
.
grey
.
shade50
,
appBar:
CustomAppBar
.
back
(
title:
"Thông tin thanh toán"
),
body:
Obx
(()
{
if
(
viewModel
.
isLoading
.
value
)
{
return
const
Center
(
child:
CircularProgressIndicator
());
}
final
previewData
=
viewModel
.
previewData
.
value
;
if
(
previewData
==
null
)
{
return
const
Center
(
child:
Text
(
'Không có dữ liệu'
));
}
final
totalPrice
=
previewData
.
totalPrice
??
0
;
final
pointValue
=
previewData
.
pointData
?.
point
??
0
;
final
finalTotal
=
usePoints
&&
previewData
.
pointData
?.
status
==
1
?
totalPrice
-
pointValue
:
totalPrice
;
return
Column
(
children:
[
Expanded
(
child:
SingleChildScrollView
(
child:
Column
(
crossAxisAlignment:
CrossAxisAlignment
.
start
,
children:
[
_buildSectionHeader
(
'Chi tiết giao dịch'
),
_buildProductInfoSection
(
previewData
),
if
(
previewData
.
pointData
!=
null
&&
previewData
.
pointData
!.
status
==
1
)
_buildPointToggleSection
(
previewData
.
pointData
!),
_buildTotalSection
(
totalPrice
,
usePoints
?
pointValue
:
0
,
finalTotal
),
_buildSavedCardsSection
(),
_buildPaymentMethodsSection
(),
const
SizedBox
(
height:
100
),
// Khoảng trống để không bị che bởi bottom bar
],
),
),
),
// Bottom bar với tổng thanh toán và nút tiếp tục
_buildBottomBar
(
finalTotal
),
],
);
}),
);
}
Widget
_buildSectionHeader
(
String
title
)
{
return
Padding
(
padding:
const
EdgeInsets
.
fromLTRB
(
16
,
16
,
16
,
8
),
child:
Text
(
title
,
style:
const
TextStyle
(
fontSize:
18
,
fontWeight:
FontWeight
.
bold
,
color:
Colors
.
black87
,
),
),
);
}
Widget
_buildProductInfoSection
(
PreviewOrderPaymentModel
data
)
{
final
productInfo
=
data
.
productInfo
??
[];
return
Container
(
color:
Colors
.
white
,
child:
Column
(
children:
productInfo
.
map
((
item
)
{
return
Padding
(
padding:
const
EdgeInsets
.
symmetric
(
horizontal:
16
,
vertical:
8
),
child:
Row
(
mainAxisAlignment:
MainAxisAlignment
.
spaceBetween
,
children:
[
Text
(
item
.
name
??
''
,
style:
TextStyle
(
fontSize:
16
,
color:
Colors
.
grey
.
shade700
,
),
),
Text
(
item
.
value
??
''
,
style:
const
TextStyle
(
fontSize:
16
,
fontWeight:
FontWeight
.
w500
,
),
),
],
),
);
}).
toList
(),
),
);
}
Widget
_buildPointToggleSection
(
PreviewOrderPaymentPointDataModel
pointData
)
{
return
Container
(
color:
Colors
.
white
,
margin:
const
EdgeInsets
.
only
(
top:
8
),
padding:
const
EdgeInsets
.
symmetric
(
horizontal:
16
,
vertical:
12
),
child:
Row
(
mainAxisAlignment:
MainAxisAlignment
.
spaceBetween
,
children:
[
Row
(
children:
[
Center
(
child:
Image
.
asset
(
'assets/images/ic_point.png'
,
width:
30
,
height:
30
),
),
const
SizedBox
(
width:
12
),
Text
(
pointData
.
textDisplay
??
''
,
style:
const
TextStyle
(
fontSize:
16
,
fontWeight:
FontWeight
.
w500
,
),
),
],
),
CupertinoSwitch
(
value:
usePoints
,
activeColor:
Colors
.
green
,
onChanged:
(
value
)
{
setState
(()
{
usePoints
=
value
;
});
},
),
],
),
);
}
Widget
_buildTotalSection
(
int
totalPrice
,
int
pointsUsed
,
int
finalTotal
)
{
return
Container
(
color:
Colors
.
white
,
margin:
const
EdgeInsets
.
only
(
top:
8
),
padding:
const
EdgeInsets
.
symmetric
(
vertical:
8
),
child:
Column
(
children:
[
_buildTotalRow
(
'Tổng số tiền'
,
totalPrice
,
false
),
if
(
pointsUsed
>
0
)
_buildTotalRow
(
'Sử dụng điểm'
,
-
pointsUsed
,
false
),
_buildTotalRow
(
'Tổng tạm tính'
,
finalTotal
,
true
),
],
),
);
}
Widget
_buildTotalRow
(
String
label
,
int
amount
,
bool
isHighlighted
)
{
final
formattedAmount
=
currencyFormatter
.
format
(
amount
);
final
displayAmount
=
amount
<
0
?
formattedAmount
:
formattedAmount
;
return
Padding
(
padding:
const
EdgeInsets
.
symmetric
(
horizontal:
16
,
vertical:
8
),
child:
Row
(
mainAxisAlignment:
MainAxisAlignment
.
spaceBetween
,
children:
[
Text
(
label
,
style:
TextStyle
(
fontSize:
16
,
color:
isHighlighted
?
Colors
.
black87
:
Colors
.
grey
.
shade700
,
),
),
Text
(
displayAmount
,
style:
TextStyle
(
fontSize:
16
,
fontWeight:
FontWeight
.
w500
,
color:
isHighlighted
&&
amount
==
0
?
Colors
.
red
:
Colors
.
black87
,
),
),
],
),
);
}
Widget
_buildSavedCardsSection
()
{
return
Obx
(()
{
final
bankAccounts
=
viewModel
.
paymentBankAccounts
;
return
Column
(
crossAxisAlignment:
CrossAxisAlignment
.
start
,
children:
[
_buildSectionHeader
(
'Tài khoản/Thẻ đã lưu'
),
Container
(
color:
Colors
.
white
,
child:
bankAccounts
.
isEmpty
?
_buildNoSavedCardsItem
()
:
Column
(
children:
List
.
generate
(
bankAccounts
.
length
,
(
index
)
=>
_buildSavedCardItem
(
bankAccounts
[
index
],
index
),
),
),
),
],
);
});
}
Widget
_buildNoSavedCardsItem
()
{
return
Padding
(
padding:
const
EdgeInsets
.
symmetric
(
horizontal:
16
,
vertical:
12
),
child:
Row
(
children:
[
Container
(
width:
40
,
height:
40
,
decoration:
BoxDecoration
(
color:
Colors
.
grey
.
shade200
,
borderRadius:
BorderRadius
.
circular
(
4
),
),
child:
const
Center
(
child:
Icon
(
Icons
.
credit_card
,
color:
Colors
.
grey
,
),
),
),
const
SizedBox
(
width:
12
),
const
Text
(
'Không có thẻ đã lưu'
,
style:
TextStyle
(
fontSize:
16
,
fontWeight:
FontWeight
.
w500
,
),
),
],
),
);
}
Widget
_buildSavedCardItem
(
PaymentBankAccountInfoModel
account
,
int
index
)
{
final
isSelected
=
selectedPaymentMethodIndex
==
-
1000
-
index
;
return
InkWell
(
onTap:
()
{
setState
(()
{
selectedPaymentMethodIndex
=
-
1000
-
index
;
// tránh đụng index method
});
},
child:
Container
(
margin:
const
EdgeInsets
.
symmetric
(
horizontal:
16
,
vertical:
8
),
padding:
const
EdgeInsets
.
all
(
12
),
decoration:
BoxDecoration
(
color:
Colors
.
white
,
border:
Border
.
all
(
color:
isSelected
?
Colors
.
red
:
Colors
.
grey
.
shade300
,
width:
1.5
,
),
borderRadius:
BorderRadius
.
circular
(
8
),
),
child:
Row
(
children:
[
if
(
account
.
bankLogo
!=
null
)
ClipRRect
(
borderRadius:
BorderRadius
.
circular
(
4
),
child:
CachedNetworkImage
(
imageUrl:
account
.
bankLogo
!,
width:
32
,
height:
32
,
placeholder:
(
context
,
url
)
=>
Container
(
width:
32
,
height:
32
,
color:
Colors
.
grey
.
shade200
,
),
errorWidget:
(
context
,
url
,
error
)
=>
Container
(
width:
32
,
height:
32
,
color:
Colors
.
grey
.
shade200
,
child:
const
Icon
(
Icons
.
error
,
size:
16
),
),
),
),
const
SizedBox
(
width:
12
),
Column
(
crossAxisAlignment:
CrossAxisAlignment
.
start
,
children:
[
Text
(
account
.
bankName
??
''
,
style:
const
TextStyle
(
fontSize:
16
,
fontWeight:
FontWeight
.
w500
,
),
),
if
(
account
.
cardNumber
!=
null
)
Text
(
'****
${account.cardNumber!.substring(account.cardNumber!.length - 4)}
'
,
style:
TextStyle
(
color:
Colors
.
grey
.
shade600
),
),
],
),
],
),
),
);
}
Widget
_buildPaymentMethodsSection
()
{
return
Obx
(()
{
final
methods
=
viewModel
.
paymentMethods
;
return
Column
(
crossAxisAlignment:
CrossAxisAlignment
.
start
,
children:
[
Padding
(
padding:
const
EdgeInsets
.
fromLTRB
(
8
,
8
,
8
,
0
),
child:
Row
(
mainAxisAlignment:
MainAxisAlignment
.
spaceBetween
,
children:
[
const
Text
(
'Phương thức thanh toán khác'
,
style:
TextStyle
(
fontSize:
18
,
fontWeight:
FontWeight
.
bold
,
color:
Colors
.
black87
,
),
),
IconButton
(
icon:
Icon
(
isPaymentMethodsExpanded
?
Icons
.
keyboard_arrow_up
:
Icons
.
keyboard_arrow_down
,
color:
Colors
.
grey
,
),
onPressed:
()
{
setState
(()
{
isPaymentMethodsExpanded
=
!
isPaymentMethodsExpanded
;
});
},
),
],
),
),
if
(
isPaymentMethodsExpanded
)
Container
(
color:
Colors
.
white
,
child:
Column
(
children:
List
.
generate
(
methods
.
length
,
(
index
)
=>
_buildPaymentMethodItem
(
methods
[
index
],
index
),
),
),
),
],
);
});
}
Widget
_buildPaymentMethodItem
(
PaymentMethodModel
method
,
int
index
)
{
final
isSelected
=
selectedPaymentMethodIndex
==
index
;
return
InkWell
(
onTap:
()
{
setState
(()
{
selectedPaymentMethodIndex
=
index
;
});
},
child:
Container
(
padding:
const
EdgeInsets
.
symmetric
(
horizontal:
4
,
vertical:
4
),
decoration:
BoxDecoration
(
border:
index
<
viewModel
.
paymentMethods
.
length
-
1
?
Border
(
bottom:
BorderSide
(
color:
Colors
.
grey
.
shade200
,
width:
0.5
))
:
null
,
),
child:
Row
(
children:
[
Radio
<
int
>(
value:
index
,
groupValue:
selectedPaymentMethodIndex
,
onChanged:
(
value
)
{
setState
(()
{
selectedPaymentMethodIndex
=
value
!;
});
},
activeColor:
Colors
.
red
,
),
if
(
method
.
logo
!=
null
&&
method
.
logo
!.
isNotEmpty
)
ClipRRect
(
borderRadius:
BorderRadius
.
circular
(
4
),
child:
CachedNetworkImage
(
imageUrl:
method
.
logo
!,
width:
32
,
height:
32
,
placeholder:
(
context
,
url
)
=>
Container
(
width:
32
,
height:
32
,
color:
Colors
.
grey
.
shade200
,
),
errorWidget:
(
context
,
url
,
error
)
=>
Container
(
width:
32
,
height:
32
,
color:
Colors
.
grey
.
shade200
,
child:
const
Icon
(
Icons
.
error
,
size:
16
),
),
),
),
const
SizedBox
(
width:
12
),
Text
(
method
.
name
??
''
,
style:
const
TextStyle
(
fontSize:
16
,
fontWeight:
FontWeight
.
w500
,
),
),
],
),
),
);
}
Widget
_buildBottomBar
(
int
finalTotal
)
{
return
Container
(
padding:
const
EdgeInsets
.
all
(
16
),
decoration:
BoxDecoration
(
color:
Colors
.
white
,
boxShadow:
[
BoxShadow
(
color:
Colors
.
black
.
withOpacity
(
0.05
),
blurRadius:
10
,
offset:
const
Offset
(
0
,
-
5
),
),
],
),
child:
Column
(
children:
[
if
((
viewModel
.
previewData
.
value
?.
feeNote
??
""
).
isNotEmpty
)
Text
(
viewModel
.
previewData
.
value
?.
feeNote
??
''
,
style:
TextStyle
(
fontSize:
12
,
color:
Colors
.
orange
.
shade700
,
),
),
const
SizedBox
(
height:
12
),
Container
(
height:
1
,
color:
Colors
.
grey
.
shade200
,
),
const
SizedBox
(
height:
12
),
Row
(
children:
[
Expanded
(
child:
Column
(
crossAxisAlignment:
CrossAxisAlignment
.
start
,
mainAxisSize:
MainAxisSize
.
min
,
children:
[
const
Text
(
'Tổng thanh toán'
,
style:
TextStyle
(
fontSize:
14
,
color:
Colors
.
grey
,
),
),
const
SizedBox
(
height:
4
),
Text
(
currencyFormatter
.
format
(
finalTotal
),
style:
const
TextStyle
(
fontSize:
22
,
fontWeight:
FontWeight
.
bold
,
),
),
],
),
),
ElevatedButton
(
onPressed:
selectedPaymentMethodIndex
>=
0
?
()
{
// Xử lý khi nhấn nút tiếp tục
final
selectedMethod
=
viewModel
.
paymentMethods
[
selectedPaymentMethodIndex
];
ScaffoldMessenger
.
of
(
context
).
showSnackBar
(
SnackBar
(
content:
Text
(
'Đang xử lý thanh toán với
${selectedMethod.name}
...'
)),
);
}
:
null
,
style:
ElevatedButton
.
styleFrom
(
backgroundColor:
Colors
.
red
,
foregroundColor:
Colors
.
white
,
padding:
const
EdgeInsets
.
symmetric
(
horizontal:
32
,
vertical:
16
),
shape:
RoundedRectangleBorder
(
borderRadius:
BorderRadius
.
circular
(
8
),
),
disabledBackgroundColor:
Colors
.
red
.
withOpacity
(
0.6
),
disabledForegroundColor:
Colors
.
white
.
withOpacity
(
0.8
),
),
child:
const
Text
(
'Tiếp tục'
,
style:
TextStyle
(
fontSize:
16
,
fontWeight:
FontWeight
.
bold
,
),
),
),
],
),
const
SizedBox
(
height:
44
),
],
),
);
}
}
\ No newline at end of file
lib/screen/transaction/transaction_detail_viewmodel.dart
0 → 100644
View file @
8bef97c9
import
'package:get/get_rx/src/rx_types/rx_types.dart'
;
import
'package:mypoint_flutter_app/networking/restful_api_request.dart'
;
import
'../../base/restful_api_viewmodel.dart'
;
import
'../../preference/data_preference.dart'
;
import
'model/payment_bank_account_info_model.dart'
;
import
'model/payment_method_model.dart'
;
import
'model/preview_order_payment_model.dart'
;
class
TransactionDetailViewModel
extends
RestfulApiViewModel
{
var
previewData
=
Rxn
<
PreviewOrderPaymentModel
>();
var
paymentMethods
=
RxList
<
PaymentMethodModel
>();
var
paymentBankAccounts
=
RxList
<
PaymentBankAccountInfoModel
>();
final
RxBool
isLoading
=
false
.
obs
;
@override
void
onInit
()
{
super
.
onInit
();
refreshData
();
}
Future
<
void
>
refreshData
()
async
{
isLoading
.
value
=
true
;
await
Future
.
wait
([
_getPreviewOrderPayment
(),
_getPaymentMethods
(),
_getPaymentBankAccounts
(),
]);
isLoading
.
value
=
false
;
}
Future
<
void
>
_getPreviewOrderPayment
()
async
{
String
?
token
=
DataPreference
.
instance
.
token
??
""
;
try
{
final
body
=
{
"product_id"
:
13796
,
"quantity"
:
1
,
"access_token"
:
token
,
"price"
:
100000
,
};
final
response
=
await
client
.
getPreviewOrderInfo
(
body
);
previewData
.
value
=
response
.
data
;
}
catch
(
error
)
{
print
(
"Error fetching preview order payment:
$error
"
);
}
}
Future
<
void
>
_getPaymentMethods
()
async
{
try
{
final
response
=
await
client
.
getPreviewPaymentMethods
();
paymentMethods
.
value
=
response
.
data
??
[];
}
catch
(
error
)
{
print
(
"Error fetching payment methods:
$error
"
);
}
}
Future
<
void
>
_getPaymentBankAccounts
()
async
{
try
{
final
response
=
await
client
.
getPreviewOrderBankAccounts
();
paymentBankAccounts
.
value
=
response
.
data
??
[];
}
catch
(
error
)
{
print
(
"Error fetching payment bank accounts:
$error
"
);
}
}
}
\ No newline at end of file
lib/screen/voucher/detail/voucher_detail_screen.dart
View file @
8bef97c9
...
...
@@ -6,6 +6,7 @@ import 'package:url_launcher/url_launcher.dart';
import
'../../../base/base_screen.dart'
;
import
'../../../base/basic_state.dart'
;
import
'../../../resouce/base_color.dart'
;
import
'../../../shared/router_gage.dart'
;
import
'../../../widgets/back_button.dart'
;
import
'../../../widgets/custom_empty_widget.dart'
;
import
'../../../widgets/custom_point_text_tag.dart'
;
...
...
@@ -378,6 +379,7 @@ class _VoucherDetailScreenState extends BaseState<VoucherDetailScreen> with Basi
height:
48
,
child:
ElevatedButton
(
onPressed:
()
{
Get
.
toNamed
(
registerFormInputScreen
,
arguments:
{
"id"
:
13484
});
// TODO: Handle đổi ưu đãi
},
style:
ElevatedButton
.
styleFrom
(
...
...
lib/screen/voucher/detail/voucher_detail_viewmodel.dart
View file @
8bef97c9
...
...
@@ -2,6 +2,7 @@ import 'package:get/get.dart';
import
'package:mypoint_flutter_app/networking/restful_api_request.dart'
;
import
'../../../base/restful_api_viewmodel.dart'
;
import
'../../../configs/constants.dart'
;
import
'../../../shared/router_gage.dart'
;
import
'../models/product_model.dart'
;
import
'../models/product_store_model.dart'
;
...
...
@@ -85,7 +86,8 @@ class VoucherDetailViewModel extends RestfulApiViewModel {
if
(!
value
.
isSuccess
)
{
onShowAlertError
?.
call
(
value
.
errorMessage
??
Constants
.
commonError
);
}
else
{
onShowAlertError
?.
call
(
"Verify Order Product Success -> Go To Payment Detail"
);
Get
.
toNamed
(
transactionDetailScreen
);
// onShowAlertError?.call("Verify Order Product Success -> Go To Payment Detail");
}
});
}
...
...
lib/shared/router_gage.dart
View file @
8bef97c9
...
...
@@ -3,8 +3,10 @@ import '../screen/game/game_cards/game_card_screen.dart';
import
'../screen/login/login_screen.dart'
;
import
'../screen/main_tab_screen/main_tab_screen.dart'
;
import
'../screen/onboarding/onboarding_screen.dart'
;
import
'../screen/register_campaign/register_form_input_screen.dart'
;
import
'../screen/setting/setting_screen.dart'
;
import
'../screen/splash/splash_screen.dart'
;
import
'../screen/transaction/transaction_detail_screen.dart'
;
import
'../screen/voucher/detail/voucher_detail_screen.dart'
;
import
'../screen/voucher/voucher_list/voucher_list_screen.dart'
;
...
...
@@ -16,6 +18,8 @@ const settingScreen = '/setting';
const
vouchersScreen
=
'/vouchers'
;
const
voucherDetailScreen
=
'/voucherDetail'
;
const
gameCardScreen
=
'/gameCardScreen'
;
const
registerFormInputScreen
=
'/registerFormInputScreen'
;
const
transactionDetailScreen
=
'/transactionDetailScreen'
;
class
RouterPage
{
static
List
<
GetPage
>
pages
()
{
...
...
@@ -34,6 +38,8 @@ class RouterPage {
GetPage
(
name:
vouchersScreen
,
page:
()
=>
VoucherListScreen
(),),
GetPage
(
name:
voucherDetailScreen
,
page:
()
=>
VoucherDetailScreen
(),),
GetPage
(
name:
gameCardScreen
,
page:
()
=>
GameCardScreen
(),),
GetPage
(
name:
registerFormInputScreen
,
page:
()
=>
RegisterFormInputScreen
(),),
GetPage
(
name:
transactionDetailScreen
,
page:
()
=>
TransactionDetailScreen
(),),
];
}
}
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