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
efb4662c
Commit
efb4662c
authored
Aug 08, 2025
by
DatHV
Browse files
update campaign 7day
parent
4c376d38
Changes
94
Expand all
Show whitespace changes
Inline
Side-by-side
lib/screen/voucher/sub_widget/voucher_item_list.dart
View file @
efb4662c
...
@@ -65,7 +65,7 @@ class VoucherListItem extends StatelessWidget {
...
@@ -65,7 +65,7 @@ class VoucherListItem extends StatelessWidget {
if
(!
product
.
inStock
)
if
(!
product
.
inStock
)
Positioned
.
fill
(
Positioned
.
fill
(
child:
Container
(
child:
Container
(
color:
Colors
.
black
.
withOpacity
(
0.
5
),
color:
Colors
.
black
.
withOpacity
(
0.
3
),
alignment:
Alignment
.
center
,
alignment:
Alignment
.
center
,
child:
const
Text
(
child:
const
Text
(
'Tạm hết'
,
'Tạm hết'
,
...
...
lib/screen/voucher/voucher_list/voucher_list_screen.dart
View file @
efb4662c
...
@@ -19,6 +19,7 @@ class _VoucherListScreenState extends State<VoucherListScreen> {
...
@@ -19,6 +19,7 @@ class _VoucherListScreenState extends State<VoucherListScreen> {
late
final
Map
<
String
,
dynamic
>
args
;
late
final
Map
<
String
,
dynamic
>
args
;
late
final
bool
enableSearch
;
late
final
bool
enableSearch
;
late
final
bool
isHotProduct
;
late
final
bool
isHotProduct
;
late
final
bool
isFavorite
;
late
final
VoucherListViewModel
_viewModel
;
late
final
VoucherListViewModel
_viewModel
;
@override
@override
...
@@ -27,12 +28,13 @@ class _VoucherListScreenState extends State<VoucherListScreen> {
...
@@ -27,12 +28,13 @@ class _VoucherListScreenState extends State<VoucherListScreen> {
args
=
Get
.
arguments
??
{};
args
=
Get
.
arguments
??
{};
enableSearch
=
args
[
'enableSearch'
]
??
false
;
enableSearch
=
args
[
'enableSearch'
]
??
false
;
isHotProduct
=
args
[
'isHotProduct'
]
??
false
;
isHotProduct
=
args
[
'isHotProduct'
]
??
false
;
_viewModel
=
Get
.
put
(
VoucherListViewModel
(
isHotProduct:
isHotProduct
));
isFavorite
=
args
[
'favorite'
]
??
false
;
_viewModel
=
Get
.
put
(
VoucherListViewModel
(
isHotProduct:
isHotProduct
,
isFavorite:
isFavorite
));
}
}
@override
@override
Widget
build
(
BuildContext
context
)
{
Widget
build
(
BuildContext
context
)
{
final
String
title
=
isHotProduct
?
'Săn ưu đãi'
:
'Tất cả ưu đãi'
;
final
String
title
=
isFavorite
?
'Yêu thích'
:
(
isHotProduct
?
'Săn ưu đãi'
:
'Tất cả ưu đãi'
)
;
return
Scaffold
(
return
Scaffold
(
appBar:
appBar:
enableSearch
enableSearch
...
@@ -69,21 +71,22 @@ class _VoucherListScreenState extends State<VoucherListScreen> {
...
@@ -69,21 +71,22 @@ class _VoucherListScreenState extends State<VoucherListScreen> {
);
);
}
}
return
RefreshIndicator
(
return
RefreshIndicator
(
onRefresh:
()
=>
_viewModel
.
getProducts
(
reset:
true
),
onRefresh:
()
=>
_viewModel
.
loadData
(
reset:
true
),
child:
ListView
.
builder
(
child:
ListView
.
builder
(
physics:
const
AlwaysScrollableScrollPhysics
(),
physics:
const
AlwaysScrollableScrollPhysics
(),
itemCount:
_viewModel
.
products
.
length
+
(
_viewModel
.
hasMore
?
1
:
0
),
itemCount:
_viewModel
.
products
.
length
+
(
_viewModel
.
hasMore
?
1
:
0
),
itemBuilder:
(
context
,
index
)
{
itemBuilder:
(
context
,
index
)
{
if
(
index
>=
_viewModel
.
products
.
length
)
{
if
(
index
>=
_viewModel
.
products
.
length
)
{
_viewModel
.
getProducts
(
reset:
false
);
_viewModel
.
loadData
(
reset:
false
);
return
const
Center
(
return
const
Center
(
child:
Padding
(
padding:
EdgeInsets
.
all
(
16
),
child:
CircularProgressIndicator
()),
child:
Padding
(
padding:
EdgeInsets
.
all
(
16
),
child:
CircularProgressIndicator
()),
);
);
}
}
final
product
=
_viewModel
.
products
[
index
];
final
product
=
_viewModel
.
products
[
index
];
return
GestureDetector
(
return
GestureDetector
(
onTap:
()
{
onTap:
()
async
{
Get
.
toNamed
(
voucherDetailScreen
,
arguments:
{
"productId"
:
product
.
id
});
await
Get
.
toNamed
(
voucherDetailScreen
,
arguments:
{
"productId"
:
product
.
id
});
_viewModel
.
loadData
(
reset:
true
);
},
},
child:
VoucherListItem
(
product:
product
),
child:
VoucherListItem
(
product:
product
),
);
);
...
...
lib/screen/voucher/voucher_list/voucher_list_viewmodel.dart
View file @
efb4662c
...
@@ -6,8 +6,8 @@ import '../models/product_model.dart';
...
@@ -6,8 +6,8 @@ import '../models/product_model.dart';
import
'../models/product_type.dart'
;
import
'../models/product_type.dart'
;
class
VoucherListViewModel
extends
RestfulApiViewModel
{
class
VoucherListViewModel
extends
RestfulApiViewModel
{
VoucherListViewModel
({
required
this
.
isHotProduct
});
VoucherListViewModel
({
required
this
.
isHotProduct
,
this
.
isFavorite
=
false
});
final
bool
isFavorite
;
final
bool
isHotProduct
;
final
bool
isHotProduct
;
Timer
?
_debounce
;
Timer
?
_debounce
;
var
products
=
<
ProductModel
>[].
obs
;
var
products
=
<
ProductModel
>[].
obs
;
...
@@ -24,7 +24,7 @@ class VoucherListViewModel extends RestfulApiViewModel {
...
@@ -24,7 +24,7 @@ class VoucherListViewModel extends RestfulApiViewModel {
@override
@override
void
onInit
()
{
void
onInit
()
{
super
.
onInit
();
super
.
onInit
();
getProducts
(
reset:
true
);
loadData
(
reset:
true
);
}
}
@override
@override
...
@@ -38,11 +38,47 @@ class VoucherListViewModel extends RestfulApiViewModel {
...
@@ -38,11 +38,47 @@ class VoucherListViewModel extends RestfulApiViewModel {
_searchQuery
=
value
;
_searchQuery
=
value
;
_debounce
?.
cancel
();
_debounce
?.
cancel
();
_debounce
=
Timer
(
const
Duration
(
seconds:
1
),
()
{
_debounce
=
Timer
(
const
Duration
(
seconds:
1
),
()
{
getProducts
(
reset:
true
);
loadData
(
reset:
true
);
});
});
}
}
Future
<
void
>
getProducts
({
bool
reset
=
false
})
async
{
Future
<
void
>
loadData
({
bool
reset
=
false
})
async
{
if
(
isFavorite
)
{
await
_getFavoriteProducts
(
reset:
reset
);
}
else
{
await
_getProducts
(
reset:
reset
);
}
}
Future
<
void
>
_getFavoriteProducts
({
bool
reset
=
false
})
async
{
if
(
isLoading
.
value
)
return
;
if
(
reset
)
{
_currentPage
=
0
;
_hasMore
=
true
;
products
.
clear
();
}
else
{
_currentPage
=
products
.
length
;
}
if
(!
_hasMore
)
return
;
final
body
=
{
"size"
:
_pageSize
,
"index"
:
_currentPage
};
try
{
isLoading
.
value
=
true
;
isLoadMore
.
value
=
true
;
final
result
=
await
client
.
productsCustomerLikes
(
body
);
final
fetchedData
=
result
.
data
??
[];
if
(
fetchedData
.
isEmpty
||
fetchedData
.
length
<
_pageSize
)
{
_hasMore
=
false
;
}
products
.
addAll
(
fetchedData
);
}
catch
(
error
)
{
print
(
"Error fetching products:
$error
"
);
}
finally
{
isLoading
.
value
=
false
;
isLoadMore
.
value
=
false
;
}
}
Future
<
void
>
_getProducts
({
bool
reset
=
false
})
async
{
if
(
isLoading
.
value
)
return
;
if
(
isLoading
.
value
)
return
;
if
(
reset
)
{
if
(
reset
)
{
_currentPage
=
0
;
_currentPage
=
0
;
...
...
lib/screen/webview/web_view_screen.dart
View file @
efb4662c
...
@@ -41,6 +41,7 @@ class _BaseWebViewScreenState extends BaseState<BaseWebViewScreen> with BasicSta
...
@@ -41,6 +41,7 @@ class _BaseWebViewScreenState extends BaseState<BaseWebViewScreen> with BasicSta
});
});
return
;
return
;
}
}
showLoading
();
_controller
=
_controller
=
WebViewController
()
WebViewController
()
..
setJavaScriptMode
(
JavaScriptMode
.
unrestricted
)
..
setJavaScriptMode
(
JavaScriptMode
.
unrestricted
)
...
@@ -48,12 +49,14 @@ class _BaseWebViewScreenState extends BaseState<BaseWebViewScreen> with BasicSta
...
@@ -48,12 +49,14 @@ class _BaseWebViewScreenState extends BaseState<BaseWebViewScreen> with BasicSta
..
setNavigationDelegate
(
..
setNavigationDelegate
(
NavigationDelegate
(
NavigationDelegate
(
onPageFinished:
(
_
)
async
{
onPageFinished:
(
_
)
async
{
hideLoading
();
final
title
=
await
_controller
.
getTitle
();
final
title
=
await
_controller
.
getTitle
();
setState
(()
{
setState
(()
{
_dynamicTitle
=
title
;
_dynamicTitle
=
title
;
});
});
},
},
onWebResourceError:
(
error
)
{
onWebResourceError:
(
error
)
{
hideLoading
();
if
(
error
.
description
!=
'about:blank'
)
{
if
(
error
.
description
!=
'about:blank'
)
{
showAlertError
(
content:
error
.
description
);
showAlertError
(
content:
error
.
description
);
}
}
...
...
lib/shared/router_gage.dart
View file @
efb4662c
...
@@ -6,9 +6,12 @@ import '../screen/affiliate/affiliate_tab_screen.dart';
...
@@ -6,9 +6,12 @@ import '../screen/affiliate/affiliate_tab_screen.dart';
import
'../screen/affiliate_brand_detail/affiliate_brand_detail_screen.dart'
;
import
'../screen/affiliate_brand_detail/affiliate_brand_detail_screen.dart'
;
import
'../screen/affiliate_brand_detail/affiliate_brand_list_screen.dart'
;
import
'../screen/affiliate_brand_detail/affiliate_brand_list_screen.dart'
;
import
'../screen/affiliate_brand_detail/affiliate_category_grid_screen.dart'
;
import
'../screen/affiliate_brand_detail/affiliate_category_grid_screen.dart'
;
import
'../screen/campaign7day/campaign_7day_screen.dart'
;
import
'../screen/contacts/contacts_list_screen.dart'
;
import
'../screen/contacts/contacts_list_screen.dart'
;
import
'../screen/daily_checkin/daily_checkin_screen.dart'
;
import
'../screen/daily_checkin/daily_checkin_screen.dart'
;
import
'../screen/data_network_service/data_network_service_screen.dart'
;
import
'../screen/data_network_service/data_network_service_screen.dart'
;
import
'../screen/electric_payment/electric_payment_history_screen.dart'
;
import
'../screen/electric_payment/electric_payment_screen.dart'
;
import
'../screen/game/game_cards/game_card_screen.dart'
;
import
'../screen/game/game_cards/game_card_screen.dart'
;
import
'../screen/game/game_tab_screen.dart'
;
import
'../screen/game/game_tab_screen.dart'
;
import
'../screen/history_point_cashback/history_point_cashback_screen.dart'
;
import
'../screen/history_point_cashback/history_point_cashback_screen.dart'
;
...
@@ -23,13 +26,17 @@ import '../screen/onboarding/onboarding_screen.dart';
...
@@ -23,13 +26,17 @@ import '../screen/onboarding/onboarding_screen.dart';
import
'../screen/order_menu/order_menu_screen.dart'
;
import
'../screen/order_menu/order_menu_screen.dart'
;
import
'../screen/pageDetail/campaign_detail_screen.dart'
;
import
'../screen/pageDetail/campaign_detail_screen.dart'
;
import
'../screen/personal/personal_edit_screen.dart'
;
import
'../screen/personal/personal_edit_screen.dart'
;
import
'../screen/quiz_campaign/quiz_campaign_screen.dart'
;
import
'../screen/register_campaign/register_form_input_screen.dart'
;
import
'../screen/register_campaign/register_form_input_screen.dart'
;
import
'../screen/setting/setting_screen.dart'
;
import
'../screen/setting/setting_screen.dart'
;
import
'../screen/splash/splash_screen.dart'
;
import
'../screen/splash/splash_screen.dart'
;
import
'../screen/support/support_screen.dart'
;
import
'../screen/support/support_screen.dart'
;
import
'../screen/topup/topup_screen.dart'
;
import
'../screen/topup/topup_screen.dart'
;
import
'../screen/traffic_service/traffic_service_detail_screen.dart'
;
import
'../screen/traffic_service/traffic_service_screen.dart'
;
import
'../screen/transaction/history/transaction_history_detail_screen.dart'
;
import
'../screen/transaction/history/transaction_history_detail_screen.dart'
;
import
'../screen/transaction/transaction_detail_screen.dart'
;
import
'../screen/transaction/transaction_detail_screen.dart'
;
import
'../screen/transaction/transactions_history_screen.dart'
;
import
'../screen/voucher/detail/voucher_detail_screen.dart'
;
import
'../screen/voucher/detail/voucher_detail_screen.dart'
;
import
'../screen/voucher/my_voucher/my_product_list_widget.dart'
;
import
'../screen/voucher/my_voucher/my_product_list_widget.dart'
;
import
'../screen/voucher/voucher_list/voucher_list_screen.dart'
;
import
'../screen/voucher/voucher_list/voucher_list_screen.dart'
;
...
@@ -73,6 +80,13 @@ const affiliateCategoryGridScreen = '/affiliateCategoryGridScreen';
...
@@ -73,6 +80,13 @@ const affiliateCategoryGridScreen = '/affiliateCategoryGridScreen';
const
inviteFriendCampaignScreen
=
'/inviteFriendCampaignScreen'
;
const
inviteFriendCampaignScreen
=
'/inviteFriendCampaignScreen'
;
const
contactsListScreen
=
'/contactsListScreen'
;
const
contactsListScreen
=
'/contactsListScreen'
;
const
dailyCheckInScreen
=
'/dailyCheckInScreen'
;
const
dailyCheckInScreen
=
'/dailyCheckInScreen'
;
const
transactionHistoryScreen
=
'/transactionHistoryScreen'
;
const
electricPaymentScreen
=
'/electricPaymentScreen'
;
const
electricPaymentHistoryScreen
=
'/electricPaymentHistoryScreen'
;
const
trafficServiceScreen
=
'/trafficServiceScreen'
;
const
trafficServiceDetailScreen
=
'/trafficServiceDetailScreen'
;
const
campaignSevenDayScreen
=
'/campaignSevenDayScreen'
;
const
surveyQuestionScreen
=
'/surveyQuestionScreen'
;
class
RouterPage
{
class
RouterPage
{
static
List
<
GetPage
>
pages
()
{
static
List
<
GetPage
>
pages
()
{
...
@@ -86,7 +100,13 @@ class RouterPage {
...
@@ -86,7 +100,13 @@ class RouterPage {
GetPage
(
name:
splashScreen
,
page:
()
=>
SplashScreen
()),
GetPage
(
name:
splashScreen
,
page:
()
=>
SplashScreen
()),
GetPage
(
name:
onboardingScreen
,
page:
()
=>
OnboardingScreen
()),
GetPage
(
name:
onboardingScreen
,
page:
()
=>
OnboardingScreen
()),
GetPage
(
name:
loginScreen
,
page:
()
=>
LoginScreen
()),
GetPage
(
name:
loginScreen
,
page:
()
=>
LoginScreen
()),
GetPage
(
name:
mainScreen
,
page:
()
=>
MainTabScreen
(),
customTransition:
NoSwipeBackTransition
()),
GetPage
(
name:
mainScreen
,
page:
()
=>
MainTabScreen
(),
participatesInRootNavigator:
true
,
fullscreenDialog:
true
,
binding:
BindingsBuilder
(()
{}),
),
GetPage
(
name:
settingScreen
,
page:
()
=>
SettingScreen
()),
GetPage
(
name:
settingScreen
,
page:
()
=>
SettingScreen
()),
GetPage
(
name:
vouchersScreen
,
page:
()
=>
VoucherListScreen
()),
GetPage
(
name:
vouchersScreen
,
page:
()
=>
VoucherListScreen
()),
GetPage
(
name:
voucherDetailScreen
,
page:
()
=>
VoucherDetailScreen
()),
GetPage
(
name:
voucherDetailScreen
,
page:
()
=>
VoucherDetailScreen
()),
...
@@ -119,20 +139,13 @@ class RouterPage {
...
@@ -119,20 +139,13 @@ class RouterPage {
GetPage
(
name:
inviteFriendCampaignScreen
,
page:
()
=>
InviteFriendCampaignScreen
()),
GetPage
(
name:
inviteFriendCampaignScreen
,
page:
()
=>
InviteFriendCampaignScreen
()),
GetPage
(
name:
contactsListScreen
,
page:
()
=>
ContactsListScreen
()),
GetPage
(
name:
contactsListScreen
,
page:
()
=>
ContactsListScreen
()),
GetPage
(
name:
dailyCheckInScreen
,
page:
()
=>
DailyCheckInScreen
()),
GetPage
(
name:
dailyCheckInScreen
,
page:
()
=>
DailyCheckInScreen
()),
GetPage
(
name:
transactionHistoryScreen
,
page:
()
=>
TransactionHistoryScreen
()),
GetPage
(
name:
electricPaymentScreen
,
page:
()
=>
ElectricPaymentScreen
()),
GetPage
(
name:
electricPaymentHistoryScreen
,
page:
()
=>
ElectricPaymentHistoryScreen
()),
GetPage
(
name:
trafficServiceScreen
,
page:
()
=>
TrafficServiceScreen
()),
GetPage
(
name:
trafficServiceDetailScreen
,
page:
()
=>
TrafficServiceDetailScreen
()),
GetPage
(
name:
campaignSevenDayScreen
,
page:
()
=>
Campaign7DayScreen
()),
GetPage
(
name:
surveyQuestionScreen
,
page:
()
=>
SurveyQuestionScreen
()),
];
];
}
}
}
}
\ No newline at end of file
class
NoSwipeBackTransition
extends
CustomTransition
{
@override
Widget
buildTransition
(
BuildContext
context
,
Curve
?
curve
,
Alignment
?
alignment
,
Animation
<
double
>
animation
,
Animation
<
double
>
secondaryAnimation
,
Widget
child
,
)
{
return
child
;
}
}
\ No newline at end of file
lib/widgets/alert/button_config_model.dart
View file @
efb4662c
...
@@ -24,7 +24,7 @@ class ButtonConfigModel {
...
@@ -24,7 +24,7 @@ class ButtonConfigModel {
final
bgColor
=
color
?.
toColor
()
??
Colors
.
white
;
final
bgColor
=
color
?.
toColor
()
??
Colors
.
white
;
return
AlertButton
(
return
AlertButton
(
text:
text
??
""
,
text:
text
??
""
,
textColor:
bgColor
.
invert
,
textColor:
bgColor
.
contrastTextColor
,
bgColor:
bgColor
,
bgColor:
bgColor
,
onPressed:
()
async
{
onPressed:
()
async
{
DirectionalScreen
?
directional
=
DirectionalScreen
.
build
(
DirectionalScreen
?
directional
=
DirectionalScreen
.
build
(
...
...
lib/widgets/alert/custom_alert_dialog.dart
View file @
efb4662c
...
@@ -24,7 +24,7 @@ class CustomAlertDialog extends StatelessWidget {
...
@@ -24,7 +24,7 @@ class CustomAlertDialog extends StatelessWidget {
return
Dialog
(
return
Dialog
(
shape:
RoundedRectangleBorder
(
borderRadius:
BorderRadius
.
circular
(
16
)),
shape:
RoundedRectangleBorder
(
borderRadius:
BorderRadius
.
circular
(
16
)),
child:
Container
(
child:
Container
(
padding:
const
EdgeInsets
.
all
(
16
),
padding:
const
EdgeInsets
.
all
(
0
),
decoration:
BoxDecoration
(
borderRadius:
BorderRadius
.
circular
(
16
),
color:
Colors
.
white
),
decoration:
BoxDecoration
(
borderRadius:
BorderRadius
.
circular
(
16
),
color:
Colors
.
white
),
child:
Stack
(
child:
Stack
(
children:
[
children:
[
...
@@ -32,8 +32,10 @@ class CustomAlertDialog extends StatelessWidget {
...
@@ -32,8 +32,10 @@ class CustomAlertDialog extends StatelessWidget {
mainAxisSize:
MainAxisSize
.
min
,
mainAxisSize:
MainAxisSize
.
min
,
children:
[
children:
[
_buildHeaderImage
(),
_buildHeaderImage
(),
const
SizedBox
(
height:
2
),
Padding
(
// Title
padding:
const
EdgeInsets
.
all
(
16
),
child:
Column
(
children:
[
if
((
alertData
.
title
??
""
).
isNotEmpty
)
if
((
alertData
.
title
??
""
).
isNotEmpty
)
Text
(
Text
(
alertData
.
title
!,
alertData
.
title
!,
...
@@ -54,16 +56,18 @@ class CustomAlertDialog extends StatelessWidget {
...
@@ -54,16 +56,18 @@ class CustomAlertDialog extends StatelessWidget {
style:
TextStyle
(
fontSize:
14
,
fontWeight:
FontWeight
.
w600
,
color:
BaseColor
.
primary500
),
style:
TextStyle
(
fontSize:
14
,
fontWeight:
FontWeight
.
w600
,
color:
BaseColor
.
primary500
),
textAlign:
TextAlign
.
center
,
textAlign:
TextAlign
.
center
,
),
),
// Buttons
const
SizedBox
(
height:
8
),
const
SizedBox
(
height:
8
),
_buildButtons
(),
_buildButtons
(),
],
],
),
),
),
],
),
// Close Button (X) ở góc phải trên
// Close Button (X) ở góc phải trên
if
(
showCloseButton
)
if
(
showCloseButton
)
Positioned
(
Positioned
(
top:
0
,
top:
8
,
right:
0
,
right:
8
,
child:
GestureDetector
(
child:
GestureDetector
(
onTap:
()
=>
Get
.
back
(),
onTap:
()
=>
Get
.
back
(),
child:
const
Icon
(
Icons
.
close
,
color:
Colors
.
black
,
size:
24
),
child:
const
Icon
(
Icons
.
close
,
color:
Colors
.
black
,
size:
24
),
...
@@ -79,11 +83,14 @@ class CustomAlertDialog extends StatelessWidget {
...
@@ -79,11 +83,14 @@ class CustomAlertDialog extends StatelessWidget {
if
((
alertData
.
urlHeaderImage
??
""
).
isNotEmpty
)
{
if
((
alertData
.
urlHeaderImage
??
""
).
isNotEmpty
)
{
return
ClipRRect
(
return
ClipRRect
(
borderRadius:
BorderRadius
.
circular
(
12
),
borderRadius:
BorderRadius
.
circular
(
12
),
child:
Container
(
// color: Colors.grey,
child:
loadNetworkImage
(
child:
loadNetworkImage
(
url:
alertData
.
urlHeaderImage
,
url:
alertData
.
urlHeaderImage
,
fit:
BoxFit
.
cover
,
fit:
BoxFit
.
fill
,
placeholderAsset:
"assets/images/ic_pipi_06.png"
,
placeholderAsset:
"assets/images/ic_pipi_06.png"
,
),
),
),
);
);
}
}
final
localHeaderImage
=
(
alertData
.
localHeaderImage
??
""
);
final
localHeaderImage
=
(
alertData
.
localHeaderImage
??
""
);
...
...
lib/widgets/bottom_sheet_helper.dart
View file @
efb4662c
...
@@ -5,6 +5,9 @@ import 'package:get/get.dart';
...
@@ -5,6 +5,9 @@ import 'package:get/get.dart';
class
BottomSheetHelper
{
class
BottomSheetHelper
{
static
void
showBottomSheetPopup
({
static
void
showBottomSheetPopup
({
required
Widget
child
,
required
Widget
child
,
Color
backgroundContainerColor
=
Colors
.
white
,
double
horizontalContainerPadding
=
8.0
,
double
bottomContainerPadding
=
16.0
,
bool
isDismissible
=
true
,
bool
isDismissible
=
true
,
})
{
})
{
showModalBottomSheet
(
showModalBottomSheet
(
...
@@ -12,11 +15,12 @@ class BottomSheetHelper {
...
@@ -12,11 +15,12 @@ class BottomSheetHelper {
isScrollControlled:
true
,
isScrollControlled:
true
,
isDismissible:
isDismissible
,
isDismissible:
isDismissible
,
backgroundColor:
Colors
.
transparent
,
backgroundColor:
Colors
.
transparent
,
barrierColor:
Colors
.
black
.
withOpacity
(
0.
5
),
barrierColor:
Colors
.
black
.
withOpacity
(
0.
7
),
shape:
const
RoundedRectangleBorder
(
shape:
const
RoundedRectangleBorder
(
borderRadius:
BorderRadius
.
vertical
(
top:
Radius
.
circular
(
16
)),
borderRadius:
BorderRadius
.
vertical
(
top:
Radius
.
circular
(
16
)),
),
),
builder:
(
context
)
{
builder:
(
context
)
{
final
bottom
=
MediaQuery
.
of
(
context
).
padding
.
bottom
;
return
Padding
(
return
Padding
(
padding:
MediaQuery
.
of
(
context
).
viewInsets
.
add
(
padding:
MediaQuery
.
of
(
context
).
viewInsets
.
add
(
const
EdgeInsets
.
only
(
bottom:
0
),
// 👈 Safe area bottom
const
EdgeInsets
.
only
(
bottom:
0
),
// 👈 Safe area bottom
...
@@ -24,11 +28,15 @@ class BottomSheetHelper {
...
@@ -24,11 +28,15 @@ class BottomSheetHelper {
child:
Wrap
(
child:
Wrap
(
children:
[
children:
[
Container
(
Container
(
decoration:
const
BoxDecoration
(
decoration:
BoxDecoration
(
color:
Colors
.
white
,
color:
backgroundContainerColor
,
borderRadius:
BorderRadius
.
vertical
(
top:
Radius
.
circular
(
16
)),
borderRadius:
const
BorderRadius
.
vertical
(
top:
Radius
.
circular
(
16
)),
),
padding:
EdgeInsets
.
only
(
left:
horizontalContainerPadding
,
right:
horizontalContainerPadding
,
bottom:
bottomContainerPadding
,
),
),
padding:
const
EdgeInsets
.
symmetric
(
horizontal:
8
,
vertical:
16
),
child:
child
,
child:
child
,
),
),
SizedBox
(
height:
32
,),
SizedBox
(
height:
32
,),
...
...
lib/widgets/custom_app_bar.dart
View file @
efb4662c
...
@@ -16,7 +16,6 @@ class CustomAppBar extends StatelessWidget implements PreferredSizeWidget {
...
@@ -16,7 +16,6 @@ class CustomAppBar extends StatelessWidget implements PreferredSizeWidget {
this
.
height
=
56
,
this
.
height
=
56
,
});
});
/// 🔥 AppBar mặc định với nút back và title
static
CustomAppBar
back
({
required
String
title
})
{
static
CustomAppBar
back
({
required
String
title
})
{
return
CustomAppBar
(
title:
title
,
leftButtons:
[
CustomBackButton
()]);
return
CustomAppBar
(
title:
title
,
leftButtons:
[
CustomBackButton
()]);
}
}
...
...
lib/widgets/custom_empty_widget.dart
View file @
efb4662c
...
@@ -9,7 +9,7 @@ class EmptyWidget extends StatelessWidget {
...
@@ -9,7 +9,7 @@ class EmptyWidget extends StatelessWidget {
super
.
key
,
super
.
key
,
this
.
imageAsset
=
'assets/images/ic_pipi_06.png'
,
this
.
imageAsset
=
'assets/images/ic_pipi_06.png'
,
this
.
content
=
'Không có dữ liệu hiển thị'
,
this
.
content
=
'Không có dữ liệu hiển thị'
,
this
.
size
=
const
Size
(
1
20
,
1
20
),
this
.
size
=
const
Size
(
2
0
0
,
2
0
0
),
});
});
@override
@override
...
...
lib/widgets/custom_navigation_bar.dart
View file @
efb4662c
...
@@ -54,7 +54,7 @@ class CustomNavigationBar extends StatelessWidget implements PreferredSizeWidget
...
@@ -54,7 +54,7 @@ class CustomNavigationBar extends StatelessWidget implements PreferredSizeWidget
Text
(
Text
(
title
,
title
,
maxLines:
1
,
maxLines:
1
,
style:
const
TextStyle
(
fontSize:
17
,
fontWeight:
FontWeight
.
bold
,
color:
Colors
.
white
),
style:
const
TextStyle
(
fontSize:
17
,
fontWeight:
FontWeight
.
w800
,
color:
Colors
.
white
),
textAlign:
TextAlign
.
center
,
textAlign:
TextAlign
.
center
,
),
),
// Back button bên trái
// Back button bên trái
...
...
lib/widgets/image_loader.dart
View file @
efb4662c
...
@@ -2,7 +2,7 @@ import 'package:flutter/material.dart';
...
@@ -2,7 +2,7 @@ import 'package:flutter/material.dart';
Widget
loadNetworkImage
(
{
Widget
loadNetworkImage
(
{
required
String
?
url
,
required
String
?
url
,
BoxFit
fit
=
BoxFit
.
co
ver
,
BoxFit
fit
=
BoxFit
.
co
ntain
,
double
?
width
,
double
?
width
,
double
?
height
,
double
?
height
,
String
placeholderAsset
=
'assets/images/ic_logo.png'
,
String
placeholderAsset
=
'assets/images/ic_logo.png'
,
...
...
lib/widgets/pick_contact.dart
deleted
100644 → 0
View file @
4c376d38
This diff is collapsed.
Click to expand it.
pubspec.yaml
View file @
efb4662c
This diff is collapsed.
Click to expand it.
Prev
1
2
3
4
5
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