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
6b980613
Commit
6b980613
authored
Nov 14, 2025
by
DatHV
Browse files
update project structure
parent
bfff9e47
Changes
507
Show whitespace changes
Inline
Side-by-side
lib/
extension
s/crypto.dart
→
lib/
core/util
s/crypto.dart
View file @
6b980613
File moved
lib/
extension
s/debouncer.dart
→
lib/
core/util
s/debouncer.dart
View file @
6b980613
File moved
lib/extensions/collection_extension.dart
→
lib/
core/utils/
extensions/collection_extension.dart
View file @
6b980613
File moved
lib/extensions/color_extension.dart
→
lib/
core/utils/
extensions/color_extension.dart
View file @
6b980613
import
'dart:ui'
;
import
'package:flutter/material.dart'
;
import
'package:flutter/material.dart'
;
extension
ColorExtension
on
Color
{
extension
ColorExtension
on
Color
{
...
...
lib/extensions/date_format.dart
→
lib/
core/utils/
extensions/date_format.dart
View file @
6b980613
File moved
lib/extensions/datetime_extensions.dart
→
lib/
core/utils/
extensions/datetime_extensions.dart
View file @
6b980613
File moved
lib/extensions/num_extension.dart
→
lib/
core/utils/
extensions/num_extension.dart
View file @
6b980613
File moved
lib/extensions/string_extension.dart
→
lib/
core/utils/
extensions/string_extension.dart
View file @
6b980613
import
'dart:convert'
;
import
'dart:convert'
;
import
'package:crypto/crypto.dart'
;
import
'package:crypto/crypto.dart'
;
import
'package:flutter/foundation.dart'
;
import
'package:flutter/material.dart'
;
import
'package:flutter/material.dart'
;
import
'package:intl/intl.dart'
as
intl
;
import
'package:intl/intl.dart'
as
intl
;
...
...
lib/utils/validation_utils.dart
→
lib/
core/
utils/validation_utils.dart
View file @
6b980613
File moved
lib/
screen
/achievement/achievement_list_screen.dart
→
lib/
features
/achievement/achievement_list_screen.dart
View file @
6b980613
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/widgets/custom_empty_widget.dart'
;
import
'package:mypoint_flutter_app/
shared/
widgets/custom_empty_widget.dart'
;
import
'package:mypoint_flutter_app/widgets/image_loader.dart'
;
import
'package:mypoint_flutter_app/
shared/
widgets/image_loader.dart'
;
import
'../../widgets/custom_navigation_bar.dart'
;
import
'../../
shared/
widgets/custom_navigation_bar.dart'
;
import
'
../home/
model
s
/achievement_model.dart'
;
import
'model/achievement_model.dart'
;
import
'achievement_viewmodel.dart'
;
import
'achievement_viewmodel.dart'
;
class
AchievementListScreen
extends
StatefulWidget
{
class
AchievementListScreen
extends
StatefulWidget
{
...
@@ -48,7 +48,7 @@ class _AchievementListScreenState extends State<AchievementListScreen> {
...
@@ -48,7 +48,7 @@ class _AchievementListScreenState extends State<AchievementListScreen> {
Widget
_buildAchievementContent
()
{
Widget
_buildAchievementContent
()
{
final
items
=
_viewModel
.
achievements
;
final
items
=
_viewModel
.
achievements
;
if
(
items
.
isEmpty
)
{
if
(
items
.
isEmpty
)
{
return
EmptyWidget
();
return
EmptyWidget
(
isLoading:
_viewModel
.
isLoading
.
value
);
}
}
return
Padding
(
return
Padding
(
padding:
const
EdgeInsets
.
all
(
16.0
),
padding:
const
EdgeInsets
.
all
(
16.0
),
...
@@ -82,7 +82,7 @@ class _AchievementListScreenState extends State<AchievementListScreen> {
...
@@ -82,7 +82,7 @@ class _AchievementListScreenState extends State<AchievementListScreen> {
Widget
_buildPointHuntingContent
()
{
Widget
_buildPointHuntingContent
()
{
final
items
=
_viewModel
.
achievements
;
final
items
=
_viewModel
.
achievements
;
return
items
.
isEmpty
return
items
.
isEmpty
?
EmptyWidget
()
?
EmptyWidget
(
isLoading:
_viewModel
.
isLoading
.
value
)
:
RefreshIndicator
(
:
RefreshIndicator
(
onRefresh:
()
=>
_viewModel
.
fetchAchievements
(),
onRefresh:
()
=>
_viewModel
.
fetchAchievements
(),
child:
CustomScrollView
(
child:
CustomScrollView
(
...
...
lib/
screen
/achievement/achievement_viewmodel.dart
→
lib/
features
/achievement/achievement_viewmodel.dart
View file @
6b980613
import
'package:get/get.dart'
;
import
'package:get/get.dart'
;
import
'package:mypoint_flutter_app/network
ing
/restful_api_client_all_request.dart'
;
import
'package:mypoint_flutter_app/
core/
network/restful_api_client_all_request.dart'
;
import
'../../network
ing
/restful_api_viewmodel.dart'
;
import
'../../
core/
network/restful_api_viewmodel.dart'
;
import
'../../preference/data_preference.dart'
;
import
'../../
shared/
preference
s
/data_preference.dart'
;
import
'
../home/
model
s
/achievement_model.dart'
;
import
'model/achievement_model.dart'
;
class
AchievementViewModel
extends
RestfulApiViewModel
{
class
AchievementViewModel
extends
RestfulApiViewModel
{
final
bool
isPointHunting
;
final
bool
isPointHunting
;
...
@@ -28,9 +28,9 @@ class AchievementViewModel extends RestfulApiViewModel {
...
@@ -28,9 +28,9 @@ class AchievementViewModel extends RestfulApiViewModel {
await
callApi
<
AchievementListResponse
>(
await
callApi
<
AchievementListResponse
>(
request:
()
=>
client
.
getAchievementList
(
body
),
request:
()
=>
client
.
getAchievementList
(
body
),
onSuccess:
(
data
,
_
)
{
onSuccess:
(
data
,
_
)
{
achievements
.
assignAll
(
data
?
.
achievements
??
[]);
achievements
.
assignAll
(
data
.
achievements
??
[]);
},
},
onFailure:
(
msg
,
_
,
_
_
)
async
{
onFailure:
(
msg
,
_
,
_
)
async
{
achievements
.
clear
();
achievements
.
clear
();
},
},
showAppNavigatorDialog:
false
,
showAppNavigatorDialog:
false
,
...
...
lib/
screen/home
/model
s
/achievement_model.dart
→
lib/
features/achievement
/model/achievement_model.dart
View file @
6b980613
import
'package:flutter/foundation.dart'
;
import
'package:flutter/foundation.dart'
;
import
'package:get/get.dart'
;
import
'package:get/get.dart'
;
import
'package:json_annotation/json_annotation.dart'
;
import
'package:json_annotation/json_annotation.dart'
;
import
'package:mypoint_flutter_app/
direc
tion
al
/directional_screen.dart'
;
import
'package:mypoint_flutter_app/
shared/naviga
tion/directional_screen.dart'
;
part
'achievement_model.g.dart'
;
part
'achievement_model.g.dart'
;
@JsonSerializable
()
@JsonSerializable
()
...
...
lib/
screen/home
/model
s
/achievement_model.g.dart
→
lib/
features/achievement
/model/achievement_model.g.dart
View file @
6b980613
File moved
lib/
screen
/affiliate/affiliate_overview.dart
→
lib/
features
/affiliate/affiliate_overview.dart
View file @
6b980613
File moved
lib/
screen
/affiliate/affiliate_popup_brands.dart
→
lib/
features
/affiliate/affiliate_popup_brands.dart
View file @
6b980613
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/widgets/image_loader.dart'
;
import
'package:mypoint_flutter_app/
shared/
widgets/image_loader.dart'
;
import
'../../
resources
/base_color.dart'
;
import
'../../
core/theme
/base_color.dart'
;
import
'../../shared/router_gage.dart'
;
import
'../../shared/router_gage.dart'
;
import
'model/affiliate_brand_model.dart'
;
import
'model/affiliate_brand_model.dart'
;
...
@@ -40,7 +40,7 @@ void showAffiliateBrandPopup(BuildContext context, List<AffiliateBrandModel> bra
...
@@ -40,7 +40,7 @@ void showAffiliateBrandPopup(BuildContext context, List<AffiliateBrandModel> bra
shrinkWrap:
true
,
shrinkWrap:
true
,
padding:
const
EdgeInsets
.
symmetric
(
vertical:
8
),
padding:
const
EdgeInsets
.
symmetric
(
vertical:
8
),
itemCount:
brands
.
length
,
itemCount:
brands
.
length
,
separatorBuilder:
(
_
,
_
_
)
=>
const
SizedBox
(
height:
4
),
separatorBuilder:
(
_
,
_
)
=>
const
SizedBox
(
height:
4
),
itemBuilder:
(
context
,
index
)
{
itemBuilder:
(
context
,
index
)
{
final
brand
=
brands
[
index
];
final
brand
=
brands
[
index
];
return
GestureDetector
(
return
GestureDetector
(
...
@@ -83,7 +83,7 @@ void showAffiliateBrandPopup(BuildContext context, List<AffiliateBrandModel> bra
...
@@ -83,7 +83,7 @@ void showAffiliateBrandPopup(BuildContext context, List<AffiliateBrandModel> bra
style:
const
TextStyle
(
color:
Colors
.
black54
,
fontSize:
13
),
style:
const
TextStyle
(
color:
Colors
.
black54
,
fontSize:
13
),
children:
[
children:
[
TextSpan
(
TextSpan
(
text:
brand
.
showCommision
??
''
,
text:
brand
.
showCommision
,
style:
const
TextStyle
(
color:
Colors
.
deepOrange
,
fontWeight:
FontWeight
.
bold
,
fontSize:
14
),
style:
const
TextStyle
(
color:
Colors
.
deepOrange
,
fontWeight:
FontWeight
.
bold
,
fontSize:
14
),
),
),
],
],
...
...
lib/
screen
/affiliate/affiliate_tab_screen.dart
→
lib/
features
/affiliate/affiliate_tab_screen.dart
View file @
6b980613
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
/affiliate/sub_widget/build_affiliate_brand.dart'
;
import
'package:mypoint_flutter_app/
features
/affiliate/sub_widget/build_affiliate_brand.dart'
;
import
'package:mypoint_flutter_app/
screen
/affiliate/sub_widget/build_affiliate_category.dart'
;
import
'package:mypoint_flutter_app/
features
/affiliate/sub_widget/build_affiliate_category.dart'
;
import
'package:mypoint_flutter_app/
screen
/affiliate/sub_widget/build_affiliate_product_topsale.dart'
;
import
'package:mypoint_flutter_app/
features
/affiliate/sub_widget/build_affiliate_product_topsale.dart'
;
import
'package:mypoint_flutter_app/widgets/back_button.dart'
;
import
'package:mypoint_flutter_app/
shared/
widgets/back_button.dart'
;
import
'../../
base
/base_screen.dart'
;
import
'../../
shared/widgets/base_view
/base_screen.dart'
;
import
'../../
base
/basic_state.dart'
;
import
'../../
shared/widgets/base_view
/basic_state.dart'
;
import
'../../
directional
/directional_action_type.dart'
;
import
'../../
app/routing
/directional_action_type.dart'
;
import
'../../
resources
/base_color.dart'
;
import
'../../
core/theme
/base_color.dart'
;
import
'../../shared/router_gage.dart'
;
import
'../../shared/router_gage.dart'
;
import
'../../widgets/bottom_sheet_helper.dart'
;
import
'../../shared/widgets/bottom_sheet_helper.dart'
;
import
'../../widgets/custom_navigation_bar.dart'
;
import
'../../shared/widgets/custom_navigation_bar.dart'
;
import
'../home/header_home_viewmodel.dart'
;
import
'../home/custom_widget/banner_carousel_widget.dart'
;
import
'../popup_manager/popup_manager_screen.dart'
;
import
'../popup_manager/popup_manager_viewmodel.dart'
;
import
'../popup_manager/popup_runner_helper.dart'
;
import
'../popup_manager/popup_runner_helper.dart'
;
import
'affiliate_overview.dart'
;
import
'affiliate_overview.dart'
;
import
'affiliate_popup_brands.dart'
;
import
'affiliate_popup_brands.dart'
;
...
@@ -39,6 +37,7 @@ class _AffiliateTabScreenState extends BaseState<AffiliateTabScreen> with BasicS
...
@@ -39,6 +37,7 @@ class _AffiliateTabScreenState extends BaseState<AffiliateTabScreen> with BasicS
_canBackButton
=
args
[
'can_back_button'
]
as
bool
;
_canBackButton
=
args
[
'can_back_button'
]
as
bool
;
}
}
viewModel
.
onShowAffiliateBrandPopup
=
(
data
)
{
viewModel
.
onShowAffiliateBrandPopup
=
(
data
)
{
if
(!
mounted
)
return
;
showAffiliateBrandPopup
(
context
,
data
.
$
1
,
title:
data
.
$
2
);
showAffiliateBrandPopup
(
context
,
data
.
$
1
,
title:
data
.
$
2
);
};
};
runPopupCheck
(
DirectionalScreenName
.
pointBack
);
runPopupCheck
(
DirectionalScreenName
.
pointBack
);
...
@@ -117,13 +116,27 @@ class _AffiliateTabScreenState extends BaseState<AffiliateTabScreen> with BasicS
...
@@ -117,13 +116,27 @@ class _AffiliateTabScreenState extends BaseState<AffiliateTabScreen> with BasicS
),
),
),
),
AffiliateBrand
(
brands:
viewModel
.
affiliateBrands
.
value
),
AffiliateBrand
(
brands:
viewModel
.
affiliateBrands
.
value
),
AffiliateCategory
(
categories:
viewModel
.
affiliateCategories
.
value
,
onTap:
(
category
)
{
if
(
viewModel
.
banners
.
isNotEmpty
)...[
const
SizedBox
(
height:
16
),
BannerCarousel
(
banners:
viewModel
.
banners
,
sectionConfig:
null
,
onTap:
(
item
)
=>
item
.
directionalScreen
?.
begin
(),
),
],
AffiliateCategory
(
categories:
viewModel
.
affiliateCategories
.
value
,
onTap:
(
category
)
{
if
(
category
.
code
==
AffiliateCategoryType
.
other
)
{
if
(
category
.
code
==
AffiliateCategoryType
.
other
)
{
Get
.
toNamed
(
affiliateCategoryGridScreen
,
arguments:
{
"categories"
:
viewModel
.
allAffiliateCategories
});
Get
.
toNamed
(
affiliateCategoryGridScreen
,
arguments:
{
"categories"
:
viewModel
.
allAffiliateCategories
},
);
return
;
return
;
}
}
viewModel
.
affiliateBrandGetListBuyCategory
(
category
);
viewModel
.
affiliateBrandGetListBuyCategory
(
category
);
},),
},
),
AffiliateProductTopSale
(
products:
viewModel
.
affiliateProducts
.
value
),
AffiliateProductTopSale
(
products:
viewModel
.
affiliateProducts
.
value
),
],
],
),
),
...
...
lib/
screen
/affiliate/affiliate_tab_viewmodel.dart
→
lib/
features
/affiliate/affiliate_tab_viewmodel.dart
View file @
6b980613
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/api/affiliate_api.dart'
deferred
as
affiliate_api
;
import
'package:mypoint_flutter_app/core/network/api/affiliate_api.dart'
deferred
as
affiliate_api
;
import
'../../base/base_response_model.dart'
;
import
'../../shared/widgets/base_view/base_response_model.dart'
;
import
'../../networking/restful_api_viewmodel.dart'
;
import
'../../core/network/restful_api_viewmodel.dart'
;
import
'../home/models/banner_model.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'
;
...
@@ -9,11 +10,11 @@ import 'model/affiliate_product_top_sale_model.dart';
...
@@ -9,11 +10,11 @@ import 'model/affiliate_product_top_sale_model.dart';
import
'model/cashback_overview_model.dart'
;
import
'model/cashback_overview_model.dart'
;
class
AffiliateTabViewModel
extends
RestfulApiViewModel
{
class
AffiliateTabViewModel
extends
RestfulApiViewModel
{
final
RxList
<
BannerModel
>
banners
=
<
BannerModel
>[].
obs
;
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
<
AffiliateCategoryModel
>
allAffiliateCategories
=
<
AffiliateCategoryModel
>[].
obs
;
final
RxList
<
AffiliateProductTopSaleModel
>
affiliateProducts
=
<
AffiliateProductTopSaleModel
>[].
obs
;
final
RxList
<
AffiliateProductTopSaleModel
>
affiliateProducts
=
<
AffiliateProductTopSaleModel
>[].
obs
;
final
RxBool
isLoading
=
false
.
obs
;
final
Rxn
<
CashbackOverviewModel
>
overview
=
Rxn
<
CashbackOverviewModel
>();
final
Rxn
<
CashbackOverviewModel
>
overview
=
Rxn
<
CashbackOverviewModel
>();
void
Function
((
List
<
AffiliateBrandModel
>,
String
)
data
)?
onShowAffiliateBrandPopup
;
void
Function
((
List
<
AffiliateBrandModel
>,
String
)
data
)?
onShowAffiliateBrandPopup
;
...
@@ -41,6 +42,7 @@ class AffiliateTabViewModel extends RestfulApiViewModel {
...
@@ -41,6 +42,7 @@ class AffiliateTabViewModel extends RestfulApiViewModel {
await
Future
.
wait
([
await
Future
.
wait
([
_getAffiliateOverview
(),
_getAffiliateOverview
(),
_getAffiliateBrandGetList
(),
_getAffiliateBrandGetList
(),
_getAffiliateBanners
(),
_getAffiliateCategoryGetList
(),
_getAffiliateCategoryGetList
(),
_getAffiliateProductTopSale
(),
_getAffiliateProductTopSale
(),
]);
]);
...
@@ -53,7 +55,7 @@ class AffiliateTabViewModel extends RestfulApiViewModel {
...
@@ -53,7 +55,7 @@ class AffiliateTabViewModel extends RestfulApiViewModel {
onSuccess:
(
data
,
_
)
{
onSuccess:
(
data
,
_
)
{
affiliateBrands
.
assignAll
(
data
);
affiliateBrands
.
assignAll
(
data
);
},
},
onFailure:
(
msg
,
_
,
_
_
)
async
{
onFailure:
(
msg
,
_
,
_
)
async
{
affiliateBrands
.
clear
();
affiliateBrands
.
clear
();
},
},
withLoading:
false
,
withLoading:
false
,
...
@@ -93,13 +95,26 @@ class AffiliateTabViewModel extends RestfulApiViewModel {
...
@@ -93,13 +95,26 @@ class AffiliateTabViewModel extends RestfulApiViewModel {
);
);
}
}
Future
<
void
>
_getAffiliateBanners
()
async
{
await
callApi
<
List
<
BannerModel
>>(
request:
()
=>
_callAffiliate
((
api
)
=>
api
.
affiliateGetBanners
()),
onSuccess:
(
data
,
_
)
{
banners
.
assignAll
(
data
);
},
onFailure:
(
msg
,
_
,
_
)
async
{
banners
.
clear
();
},
withLoading:
false
,
);
}
Future
<
void
>
_getAffiliateOverview
()
async
{
Future
<
void
>
_getAffiliateOverview
()
async
{
await
callApi
<
CashbackOverviewModel
>(
await
callApi
<
CashbackOverviewModel
>(
request:
()
=>
_callAffiliate
((
api
)
=>
api
.
getCashBackOverview
()),
request:
()
=>
_callAffiliate
((
api
)
=>
api
.
getCashBackOverview
()),
onSuccess:
(
data
,
_
)
{
onSuccess:
(
data
,
_
)
{
overview
.
value
=
data
;
overview
.
value
=
data
;
},
},
onFailure:
(
msg
,
_
,
_
_
)
async
{
onFailure:
(
msg
,
_
,
_
)
async
{
overview
.
value
=
null
;
overview
.
value
=
null
;
},
},
withLoading:
false
,
withLoading:
false
,
...
@@ -114,7 +129,7 @@ class AffiliateTabViewModel extends RestfulApiViewModel {
...
@@ -114,7 +129,7 @@ class AffiliateTabViewModel extends RestfulApiViewModel {
),
),
onSuccess:
(
data
,
_
)
{
onSuccess:
(
data
,
_
)
{
if
(
data
.
isNotEmpty
)
{
if
(
data
.
isNotEmpty
)
{
onShowAffiliateBrandPopup
?.
call
((
data
,
category
.
name
??
''
));
onShowAffiliateBrandPopup
?.
call
((
data
,
category
.
name
));
}
}
},
},
);
);
...
...
lib/
screen
/affiliate/model/affiliate_brand_model.dart
→
lib/
features
/affiliate/model/affiliate_brand_model.dart
View file @
6b980613
import
'package:json_annotation/json_annotation.dart'
;
import
'package:json_annotation/json_annotation.dart'
;
import
'../../../config
s
/constants.dart'
;
import
'../../../
app/
config/constants.dart'
;
import
'../../../
directional
/directional_action_type.dart'
;
import
'../../../
app/routing
/directional_action_type.dart'
;
import
'../../../
direc
tion
al
/directional_screen.dart'
;
import
'../../../
shared/naviga
tion/directional_screen.dart'
;
part
'affiliate_brand_model.g.dart'
;
part
'affiliate_brand_model.g.dart'
;
@JsonSerializable
()
@JsonSerializable
()
...
...
lib/
screen
/affiliate/model/affiliate_brand_model.g.dart
→
lib/
features
/affiliate/model/affiliate_brand_model.g.dart
View file @
6b980613
File moved
lib/
screen
/affiliate/model/affiliate_category_model.dart
→
lib/
features
/affiliate/model/affiliate_category_model.dart
View file @
6b980613
File moved
Prev
1
2
3
4
5
6
7
8
…
26
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