Commit 6b980613 authored by DatHV's avatar DatHV
Browse files

update project structure

parent bfff9e47
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:mypoint_flutter_app/extensions/num_extension.dart';
import 'package:mypoint_flutter_app/widgets/image_loader.dart';
import '../../../widgets/custom_empty_widget.dart';
import '../../widgets/custom_navigation_bar.dart';
import 'package:mypoint_flutter_app/core/utils/extensions/num_extension.dart';
import 'package:mypoint_flutter_app/shared/widgets/image_loader.dart';
import '../../shared/widgets/custom_empty_widget.dart';
import '../../shared/widgets/custom_navigation_bar.dart';
import 'history_point_cashback_viewmodel.dart';
import 'models/history_point_cashback_model.dart';
......@@ -26,7 +26,6 @@ class _HistoryPointCashBackScreenState extends State<HistoryPointCashBackScreen>
@override
Widget build(BuildContext context) {
final screenWidth = MediaQuery.of(context).size.width;
return Scaffold(
appBar: CustomNavigationBar(title: "Lịch sử hoàn điểm"),
body: Column(
......@@ -62,12 +61,13 @@ class _HistoryPointCashBackScreenState extends State<HistoryPointCashBackScreen>
),
),
),
if (_viewModel.orders.isEmpty)
Expanded(child: EmptyWidget(size: Size(screenWidth / 2, screenWidth / 2)))
else
Obx(
() => Expanded(
child: RefreshIndicator(
Expanded(
child: Obx(
() {
if (_viewModel.orders.isEmpty) {
return EmptyWidget(isLoading: _viewModel.isLoading.value);
}
return RefreshIndicator(
onRefresh: () async {
_viewModel.freshData(isRefresh: true);
},
......@@ -85,9 +85,10 @@ class _HistoryPointCashBackScreenState extends State<HistoryPointCashBackScreen>
return _buildVoucherItem(order);
},
),
),
),
);
},
),
),
],
),
);
......
import 'package:get/get_rx/src/rx_types/rx_types.dart';
import 'package:mypoint_flutter_app/extensions/collection_extension.dart';
import 'package:mypoint_flutter_app/networking/restful_api_client_all_request.dart';
import '../../networking/restful_api_viewmodel.dart';
import 'package:mypoint_flutter_app/core/utils/extensions/collection_extension.dart';
import 'package:mypoint_flutter_app/core/network/restful_api_client_all_request.dart';
import '../../core/network/restful_api_viewmodel.dart';
import 'models/history_point_cashback_model.dart';
class HistoryPointCashBackViewModel extends RestfulApiViewModel {
......
import 'package:flutter/material.dart';
import 'package:mypoint_flutter_app/extensions/datetime_extensions.dart';
import '../../../extensions/date_format.dart';
import 'package:mypoint_flutter_app/core/utils/extensions/datetime_extensions.dart';
class HistoryPointCashBackResponse {
final double points;
......
import 'package:flutter/material.dart';
import '../../../widgets/image_loader.dart';
import '../../../shared/widgets/image_loader.dart';
import '../../voucher/sub_widget/voucher_section_title.dart';
import '../models/achievement_model.dart';
import '../../achievement/model/achievement_model.dart';
import '../models/main_section_config_model.dart';
class AchievementCarousel extends StatelessWidget {
......@@ -33,7 +33,7 @@ class AchievementCarousel extends StatelessWidget {
scrollDirection: Axis.horizontal,
padding: const EdgeInsets.symmetric(horizontal: 16),
itemCount: items.length,
separatorBuilder: (_, __) => const SizedBox(width: 12),
separatorBuilder: (_, _) => const SizedBox(width: 12),
itemBuilder: (context, index) => AchievementCard(
achievement: items[index],
onTap: () => onTap?.call(items[index]),
......
import 'package:flutter/material.dart';
import 'package:mypoint_flutter_app/extensions/string_extension.dart';
import 'package:mypoint_flutter_app/core/utils/extensions/string_extension.dart';
import '../../affiliate/model/affiliate_brand_model.dart';
import '../../voucher/sub_widget/voucher_section_title.dart';
import '../models/main_section_config_model.dart';
......@@ -11,7 +11,7 @@ class AffiliateBrandGridWidget extends StatelessWidget {
const AffiliateBrandGridWidget({super.key, required this.affiliateBrands, this.sectionConfig, this.onTap});
_handleTapRightButton() {
void _handleTapRightButton() {
sectionConfig?.buttonViewAll?.directionalScreen?.begin();
}
......@@ -74,7 +74,7 @@ class AffiliateBrandGridWidget extends StatelessWidget {
child: Image.network(
brand.logo ?? '',
fit: BoxFit.contain,
errorBuilder: (_, __, ___) => const Icon(Icons.broken_image),
errorBuilder: (_, _, _) => const Icon(Icons.broken_image),
),
),
),
......
......@@ -22,12 +22,16 @@ class _BannerCarouselState extends State<BannerCarousel> {
Timer? _autoPlayTimer;
final bool _isDragging = false;
bool _isUserScrolling = false;
double? _firstBannerAspectRatio; // height / width
String? _aspectRatioSourceUrl;
static const double _defaultAspectRatio = 535 / 1125;
@override
void initState() {
super.initState();
_controller = InfiniteScrollController(initialItem: 0);
_startAutoPlay();
_resolveFirstBannerAspectRatio();
}
void _startAutoPlay() {
......@@ -55,13 +59,57 @@ class _BannerCarouselState extends State<BannerCarousel> {
super.dispose();
}
_handleTapRightButton() {
@override
void didUpdateWidget(covariant BannerCarousel oldWidget) {
super.didUpdateWidget(oldWidget);
final oldUrl = oldWidget.banners.isNotEmpty ? oldWidget.banners.first.itemImage : null;
final newUrl = widget.banners.isNotEmpty ? widget.banners.first.itemImage : null;
if (oldUrl != newUrl) {
_firstBannerAspectRatio = null;
_aspectRatioSourceUrl = null;
_resolveFirstBannerAspectRatio();
}
}
void _resolveFirstBannerAspectRatio() {
if (widget.banners.isEmpty) return;
final url = widget.banners.first.itemImage;
if ((url ?? '').isEmpty || url == _aspectRatioSourceUrl) {
return;
}
_aspectRatioSourceUrl = url;
final provider = NetworkImage(url!);
final stream = provider.resolve(const ImageConfiguration());
late ImageStreamListener listener;
listener = ImageStreamListener(
(info, _) {
final ratio = info.image.height / info.image.width;
if (mounted) {
setState(() {
_firstBannerAspectRatio = ratio;
});
}
stream.removeListener(listener);
},
onError: (_, _) {
stream.removeListener(listener);
},
);
stream.addListener(listener);
}
void _handleTapRightButton() {
widget.sectionConfig?.buttonViewAll?.directionalScreen?.begin();
}
double _currentBannerAspectRatio() {
return _firstBannerAspectRatio ?? _defaultAspectRatio;
}
@override
Widget build(BuildContext context) {
final width = MediaQuery.of(context).size.width * 0.9;
final height = width * _currentBannerAspectRatio() + 16;
return Column(
children: [
if ((widget.sectionConfig?.name ?? "").isNotEmpty)
......@@ -69,66 +117,74 @@ class _BannerCarouselState extends State<BannerCarousel> {
title: widget.sectionConfig?.name ?? "",
onViewAll: widget.sectionConfig?.buttonViewAll?.directionalScreen != null ? _handleTapRightButton : null,
),
GestureDetector(
onPanDown: (_) => _pauseAutoPlayTemporarily(),
child: SizedBox(
height: width * 135 / 343 + 16,
child: Stack(
alignment: Alignment.bottomCenter,
children: [
InfiniteCarousel.builder(
itemCount: widget.banners.length,
itemExtent: width,
scrollBehavior: ScrollConfiguration.of(context).copyWith(scrollbars: false),
loop: true,
center: true,
anchor: 0.0,
velocityFactor: 0.1, // ✅ fix lỗi: snap từng page
controller: _controller,
onIndexChanged: (index) => setState(() => _currentIndex = index % widget.banners.length),
itemBuilder: (context, itemIndex, realIndex) {
return GestureDetector(
onTap: () => widget.onTap?.call(widget.banners[itemIndex % widget.banners.length]),
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 4.0, vertical: 8.0),
child: ClipRRect(
borderRadius: BorderRadius.circular(12),
child: Image.network(
widget.banners[itemIndex % widget.banners.length].itemImage ?? "",
fit: BoxFit.cover,
width: double.infinity,
if (widget.banners.isNotEmpty)
GestureDetector(
onPanDown: (_) => _pauseAutoPlayTemporarily(),
child: SizedBox(
// height: width * 135 / 343 + 16,
height: height,
child: Stack(
alignment: Alignment.bottomCenter,
children: [
InfiniteCarousel.builder(
itemCount: widget.banners.length,
itemExtent: width,
scrollBehavior: ScrollConfiguration.of(context).copyWith(scrollbars: false),
loop: true,
center: true,
anchor: 0.0,
velocityFactor: 0.1,
controller: _controller,
onIndexChanged: (index) => setState(() => _currentIndex = index % widget.banners.length),
itemBuilder: (context, itemIndex, realIndex) {
final bannerIndex = itemIndex % widget.banners.length;
final ratio = _currentBannerAspectRatio();
return GestureDetector(
onTap: () => widget.onTap?.call(widget.banners[bannerIndex]),
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 4.0, vertical: 8.0),
child: AspectRatio(
aspectRatio: ratio <= 0 ? 1125 / 535 : 1 / ratio,
child: ClipRRect(
borderRadius: BorderRadius.circular(12),
child: Image.network(
widget.banners[bannerIndex].itemImage ?? "",
fit: BoxFit.cover,
width: double.infinity,
),
),
),
),
),
);
},
),
Positioned(
bottom: 12,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children:
widget.banners.asMap().entries.map((entry) {
return GestureDetector(
onTap:
() => _controller.animateToItem(entry.key, duration: const Duration(milliseconds: 500)),
child: Container(
width: 8.0,
height: 8.0,
margin: const EdgeInsets.symmetric(horizontal: 4.0),
decoration: BoxDecoration(
shape: BoxShape.circle,
color: _currentIndex == entry.key ? Colors.white : Colors.white.withOpacity(0.4),
);
},
),
Positioned(
bottom: 12,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children:
widget.banners.asMap().entries.map((entry) {
return GestureDetector(
onTap:
() =>
_controller.animateToItem(entry.key, duration: const Duration(milliseconds: 500)),
child: Container(
width: 8.0,
height: 8.0,
margin: const EdgeInsets.symmetric(horizontal: 4.0),
decoration: BoxDecoration(
shape: BoxShape.circle,
color: _currentIndex == entry.key ? Colors.white : Colors.white.withOpacity(0.4),
),
),
),
);
}).toList(),
);
}).toList(),
),
),
),
],
],
),
),
),
),
],
);
}
......
import 'package:flutter/material.dart';
import 'package:mypoint_flutter_app/extensions/string_extension.dart';
import 'package:mypoint_flutter_app/widgets/image_loader.dart';
import 'package:mypoint_flutter_app/shared/widgets/image_loader.dart';
import '../../voucher/sub_widget/voucher_section_title.dart';
import '../models/brand_model.dart';
import '../../affiliate_brand_detail/models/brand_model.dart';
import '../models/main_section_config_model.dart';
class BrandGridWidget extends StatelessWidget {
......
import 'package:flutter/material.dart';
import 'package:mypoint_flutter_app/extensions/num_extension.dart';
import 'package:mypoint_flutter_app/widgets/image_loader.dart';
import 'package:mypoint_flutter_app/core/utils/extensions/num_extension.dart';
import 'package:mypoint_flutter_app/shared/widgets/image_loader.dart';
import '../../voucher/models/product_model.dart';
import '../../voucher/sub_widget/voucher_section_title.dart';
import '../models/main_section_config_model.dart';
import 'flash_sale_header_widget.dart';
......
......@@ -80,7 +80,6 @@ class _FlashSaleHeaderState extends State<FlashSaleHeader> {
}
Widget _buildCountdownSection(Duration duration) {
final bool isCounting = duration.inSeconds > 0;
final label = (widget.flashSale?.desTime ?? 'Kết thúc trong');
return Row(
mainAxisSize: MainAxisSize.min,
......
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:mypoint_flutter_app/extensions/num_extension.dart';
import 'package:mypoint_flutter_app/widgets/image_loader.dart';
import '../../../preference/data_preference.dart';
import '../../../preference/point/header_home_model.dart';
import '../../../preference/point/point_manager.dart';
import 'package:mypoint_flutter_app/core/utils/extensions/num_extension.dart';
import 'package:mypoint_flutter_app/shared/widgets/image_loader.dart';
import '../../../shared/preferences/data_preference.dart';
import '../../../shared/preferences/point/point_manager.dart';
import '../../../shared/router_gage.dart';
import '../models/notification_unread_model.dart';
import '../models/header_home_model.dart';
import '../../notification/models/notification_unread_model.dart';
class HomeGreetingHeader extends StatelessWidget {
final double? heightContent;
......
import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.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';
class HoverView extends StatefulWidget {
final String imagePath;
......@@ -31,7 +30,7 @@ class HoverView extends StatefulWidget {
class _HoverViewState extends State<HoverView> {
Offset _position = const Offset(0, 0);
bool _isDragging = false;
bool _showCloseButton = false;
// bool _showCloseButton = true;
Size _screenSize = Size.zero;
bool _isInitialized = false;
final _remainingSeconds = 0.obs;
......@@ -89,7 +88,7 @@ class _HoverViewState extends State<HoverView> {
void _onPanStart(DragStartDetails details) {
setState(() {
_isDragging = true;
_showCloseButton = true;
// _showCloseButton = true;
});
}
......@@ -148,7 +147,7 @@ class _HoverViewState extends State<HoverView> {
// Animate to nearest corner using setState
setState(() {
_position = nearestCorner;
_showCloseButton = false;
// _showCloseButton = false;
});
}
......@@ -158,6 +157,9 @@ class _HoverViewState extends State<HoverView> {
}
}
void _onLongPress() {
}
void _onClose() {
if (widget.onClose != null) {
widget.onClose!();
......@@ -196,11 +198,7 @@ class _HoverViewState extends State<HoverView> {
onPanUpdate: _onPanUpdate,
onPanEnd: _onPanEnd,
onTap: _onTap,
onLongPress: () {
setState(() {
_showCloseButton = !_showCloseButton;
});
},
onLongPress: _onLongPress,
child: Stack(
clipBehavior: Clip.none,
children: [
......@@ -208,7 +206,7 @@ class _HoverViewState extends State<HoverView> {
Column(
children: [
AnimatedScale(
scale: _isDragging ? 1.1 : 1.0,
scale: _isDragging ? 1.2 : 1.0,
duration: const Duration(milliseconds: 200),
child: SizedBox(
width: widget.size,
......@@ -237,7 +235,7 @@ class _HoverViewState extends State<HoverView> {
],
),
// Close button
if (_showCloseButton)
// if (_showCloseButton)
Positioned(
top: -8,
right: -8,
......
import 'package:flutter/material.dart';
import '../../../widgets/image_loader.dart';
import '../../../shared/widgets/image_loader.dart';
import '../../voucher/sub_widget/voucher_section_title.dart';
import '../models/main_section_config_model.dart';
import '../models/main_service_model.dart';
......
import 'package:flutter/material.dart';
import 'package:mypoint_flutter_app/widgets/image_loader.dart';
import 'package:mypoint_flutter_app/shared/widgets/image_loader.dart';
import '../../voucher/sub_widget/voucher_section_title.dart';
import '../models/main_section_config_model.dart';
import '../models/my_product_model.dart';
import '../../voucher/models/my_product_model.dart';
class MyProductCarouselWidget extends StatelessWidget {
final List<MyProductModel> items;
......@@ -33,7 +33,7 @@ class MyProductCarouselWidget extends StatelessWidget {
scrollDirection: Axis.horizontal,
padding: const EdgeInsets.symmetric(horizontal: 16),
itemCount: items.length,
separatorBuilder: (_, __) => const SizedBox(width: 12),
separatorBuilder: (_, _) => const SizedBox(width: 12),
itemBuilder: (context, index) => _buildItem(context, items[index], widthItem),
),
),
......@@ -88,7 +88,7 @@ class MyProductCarouselWidget extends StatelessWidget {
overflow: TextOverflow.ellipsis,
),
const SizedBox(height: 2),
Text('HSD: ${product.expire ?? ''}', style: const TextStyle(fontSize: 13, color: Colors.black54)),
Text('HSD: ${product.expire}', style: const TextStyle(fontSize: 13, color: Colors.black54)),
],
),
),
......
import 'package:flutter/material.dart';
import 'package:mypoint_flutter_app/widgets/image_loader.dart';
import 'package:mypoint_flutter_app/shared/widgets/image_loader.dart';
import '../../faqs/faqs_model.dart';
import '../../voucher/sub_widget/voucher_section_title.dart';
import '../models/main_section_config_model.dart';
......@@ -32,7 +31,7 @@ class NewsCarouselWidget extends StatelessWidget {
scrollDirection: Axis.horizontal,
padding: const EdgeInsets.symmetric(horizontal: 16),
itemCount: items.length,
separatorBuilder: (_, __) => const SizedBox(width: 12),
separatorBuilder: (_, _) => const SizedBox(width: 12),
itemBuilder: (context, index) => _buildItem(context, items[index]),
),
),
......
import 'package:flutter/material.dart';
import 'package:mypoint_flutter_app/widgets/image_loader.dart';
import '../../../widgets/custom_point_text_tag.dart';
import 'package:mypoint_flutter_app/shared/widgets/image_loader.dart';
import '../../../shared/widgets/custom_point_text_tag.dart';
import '../../voucher/models/product_model.dart';
import '../../voucher/sub_widget/voucher_section_title.dart';
import '../models/main_section_config_model.dart';
......@@ -13,7 +13,7 @@ class ProductGrid extends StatelessWidget {
const ProductGrid({super.key, required this.products, this.sectionConfig, this.onTap});
_handleTapRightButton() {
void _handleTapRightButton() {
sectionConfig?.buttonViewAll?.directionalScreen?.begin();
}
......
import 'package:get/get.dart';
import 'package:mypoint_flutter_app/networking/api/notification_api.dart'
deferred as notification_api;
import 'package:mypoint_flutter_app/networking/restful_api_client_all_request.dart';
import 'package:mypoint_flutter_app/preference/data_preference.dart';
import '../../networking/restful_api_viewmodel.dart';
import '../../preference/point/point_manager.dart';
import '../../preference/point/header_home_model.dart';
import 'models/notification_unread_model.dart';
import 'package:mypoint_flutter_app/core/network/api/notification_api.dart' deferred as notification_api;
import 'package:mypoint_flutter_app/core/network/restful_api_client_all_request.dart';
import 'package:mypoint_flutter_app/shared/preferences/data_preference.dart';
import '../../core/network/restful_api_viewmodel.dart';
import '../../shared/preferences/point/point_manager.dart';
import 'models/header_home_model.dart';
import '../notification/models/notification_unread_model.dart';
class HeaderHomeRepository extends RestfulApiViewModel {
HeaderHomeRepository._();
......
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:mypoint_flutter_app/preference/point/point_manager.dart';
import 'package:mypoint_flutter_app/screen/home/custom_widget/header_home_widget.dart';
import 'package:mypoint_flutter_app/screen/home/custom_widget/product_grid_widget.dart';
import 'package:mypoint_flutter_app/screen/pipi/pipi_detail_screen.dart';
import 'package:mypoint_flutter_app/screen/voucher/models/product_model.dart';
import 'package:mypoint_flutter_app/features/home/custom_widget/header_home_widget.dart';
import 'package:mypoint_flutter_app/features/home/custom_widget/product_grid_widget.dart';
import 'package:mypoint_flutter_app/features/pipi/pipi_detail_screen.dart';
import 'package:mypoint_flutter_app/features/voucher/models/product_model.dart';
import 'package:mypoint_flutter_app/shared/router_gage.dart';
import '../../directional/directional_action_type.dart';
import '../../widgets/custom_empty_widget.dart';
import '../../shared/widgets/base_view/base_screen.dart';
import '../../shared/widgets/base_view/basic_state.dart';
import '../../app/routing/directional_action_type.dart';
import '../../shared/widgets/custom_empty_widget.dart';
import '../popup_manager/popup_runner_helper.dart';
import 'custom_widget/achievement_carousel_widget.dart';
import 'custom_widget/affiliate_brand_grid_widget.dart';
......@@ -21,25 +22,29 @@ import 'custom_widget/news_carousel_widget.dart';
import 'header_home_viewmodel.dart';
import 'home_tab_viewmodel.dart';
import 'models/header_section_type.dart';
import 'models/hover_data_model.dart';
import 'models/main_section_config_model.dart';
class HomeScreen extends StatefulWidget {
class HomeScreen extends BaseScreen {
const HomeScreen({super.key});
@override
State<HomeScreen> createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> with PopupOnInit {
class _HomeScreenState extends BaseState<HomeScreen> with PopupOnInit, BasicState {
final HomeTabViewModel _viewModel = Get.put(HomeTabViewModel());
final _headerHomeVM = Get.find<HeaderHomeViewModel>();
final RxBool _showHover = true.obs;
final RxBool _showHover = false.obs;
late final Worker _hoverDataWorker;
bool _isRefreshingFlashSale = false;
@override
void initState() {
super.initState();
UserPointManager().fetchUserPoint();
debugPrint('HomeScreen initState');
// UserPointManager().fetchUserPoint();
_hoverDataWorker = ever<HoverDataModel?>(_viewModel.hoverData, _onHoverDataChanged);
_headerHomeVM.freshData();
runPopupCheck(DirectionalScreenName.home);
}
......@@ -70,7 +75,12 @@ class _HomeScreenState extends State<HomeScreen> with PopupOnInit {
List<Widget> _buildSectionContent() {
final sections = _viewModel.sectionLayouts.map(_buildSection).whereType<Widget>().toList();
if (sections.isEmpty) {
return const [Padding(padding: EdgeInsets.symmetric(vertical: 40), child: EmptyWidget())];
return [
Padding(
padding: const EdgeInsets.symmetric(vertical: 40),
child: EmptyWidget(isLoading: _viewModel.isLoading.value),
),
];
}
return sections;
}
......@@ -153,7 +163,7 @@ class _HomeScreenState extends State<HomeScreen> with PopupOnInit {
}
@override
Widget build(BuildContext context) {
Widget createBody() {
final paddingBottom = MediaQuery.of(context).padding.bottom + 20;
final width = MediaQuery.of(context).size.width;
final heightHeader = width * 86 / 375 + 112;
......@@ -203,14 +213,66 @@ class _HomeScreenState extends State<HomeScreen> with PopupOnInit {
}
void _handleCloseHoverView() {
setState(() {
_handleCloseHoverViewInternal();
}
void _handleCloseHoverViewInternal({bool dismissedByUser = true}) {
if (dismissedByUser) {
_viewModel.hoverDismissed = true;
}
if (mounted) {
_showHover.value = false;
});
}
}
Future<void> _onRefresh() async {
_resetHoverViewState();
await _viewModel.getSectionLayoutHome(showLoading: false);
await _viewModel.loadDataPiPiHome();
await _headerHomeVM.freshData();
}
@override
void onDispose() {
_hoverDataWorker.dispose();
_pauseCountdown();
super.onDispose();
}
@override
void onRouteWillDisappear() {
super.onRouteWillDisappear();
_pauseCountdown();
}
@override
void onRouteDidAppear() {
super.onRouteDidAppear();
if (_viewModel.hoverDismissed) return;
_viewModel.loadDataPiPiHome();
}
void _pauseCountdown() {
_handleCloseHoverViewInternal(dismissedByUser: false);
}
void _resetHoverViewState() {
_viewModel.hoverDismissed = false;
_updateHoverVisibility();
}
void _updateHoverVisibility() {
if (_viewModel.hoverDismissed || !mounted) return;
_showHover.value = _shouldShowHover(_viewModel.hoverData.value);
}
void _onHoverDataChanged(HoverDataModel? data) {
if (_viewModel.hoverDismissed || !mounted) return;
_showHover.value = _shouldShowHover(data);
}
bool _shouldShowHover(HoverDataModel? data) {
if (data == null) return false;
return data.icon?.isNotEmpty == true;
}
}
......@@ -2,20 +2,20 @@ import 'dart:convert';
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
import 'package:get/get.dart';
import 'package:mypoint_flutter_app/networking/restful_api_client_all_request.dart';
import '../../networking/restful_api_viewmodel.dart';
import 'package:mypoint_flutter_app/core/network/restful_api_client_all_request.dart';
import '../../core/network/restful_api_viewmodel.dart';
import '../affiliate/model/affiliate_brand_model.dart';
import '../faqs/faqs_model.dart';
import '../voucher/models/product_model.dart';
import 'models/achievement_model.dart';
import '../achievement/model/achievement_model.dart';
import 'models/banner_model.dart';
import 'models/brand_model.dart';
import 'models/flash_sale_model.dart';
import '../affiliate_brand_detail/models/brand_model.dart';
import '../flash_sale/models/flash_sale_model.dart';
import 'models/header_section_type.dart';
import 'models/hover_data_model.dart';
import 'models/main_section_config_model.dart';
import 'models/main_service_model.dart';
import 'models/my_product_model.dart';
import '../voucher/models/my_product_model.dart';
class HomeTabViewModel extends RestfulApiViewModel {
final RxList<ProductModel> products = <ProductModel>[].obs;
......@@ -29,6 +29,7 @@ class HomeTabViewModel extends RestfulApiViewModel {
final RxList<MainSectionConfigModel> sectionLayouts = <MainSectionConfigModel>[].obs;
final Rxn<FlashSaleModel> flashSaleData = Rxn<FlashSaleModel>();
final Rxn<HoverDataModel> hoverData = Rxn<HoverDataModel>();
bool hoverDismissed = false;
late final Map<HeaderSectionType, Future<void> Function(MainSectionConfigModel)> _sectionLoaders;
......@@ -47,7 +48,6 @@ class HomeTabViewModel extends RestfulApiViewModel {
HeaderSectionType.myProduct: _loadMyProducts,
};
getSectionLayoutHome();
loadDataPiPiHome();
}
MainSectionConfigModel? getMainSectionConfigModel(HeaderSectionType type) {
......
import 'package:json_annotation/json_annotation.dart';
import 'package:mypoint_flutter_app/directional/directional_screen.dart';
import 'package:mypoint_flutter_app/shared/navigation/directional_screen.dart';
part 'banner_model.g.dart';
@JsonSerializable()
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment