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

update project structure

parent bfff9e47
import 'package:json_annotation/json_annotation.dart';
import 'package:mypoint_flutter_app/screen/splash/models/check_update_response_model.dart';
import 'package:mypoint_flutter_app/features/splash/models/check_update_response_model.dart';
part 'update_response_model.g.dart';
......
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:mypoint_flutter_app/screen/splash/splash_screen_viewmodel.dart';
import 'package:mypoint_flutter_app/widgets/alert/custom_alert_dialog.dart';
import '../../base/base_screen.dart';
import '../../base/basic_state.dart';
import 'package:mypoint_flutter_app/features/splash/splash_screen_viewmodel.dart';
import 'package:mypoint_flutter_app/shared/widgets/alert/custom_alert_dialog.dart';
import 'package:mypoint_flutter_app/core/services/web/web_helper.dart';
import '../../shared/widgets/base_view/base_screen.dart';
import '../../shared/widgets/base_view/basic_state.dart';
import 'models/check_update_response_model.dart';
import '../../resources/base_color.dart';
import '../../widgets/alert/data_alert_model.dart';
import '../../core/theme/base_color.dart';
import '../../shared/widgets/alert/data_alert_model.dart';
class SplashScreen extends BaseScreen {
const SplashScreen({super.key});
......@@ -18,11 +19,12 @@ class SplashScreen extends BaseScreen {
class _SplashScreenState extends BaseState<SplashScreen> with BasicState {
final SplashScreenViewModel _viewModel = Get.put(SplashScreenViewModel());
Future<void>? _webSplashCacheFuture;
bool _webLoaderNotified = false;
@override
void initState() {
super.initState();
print('🚀 SplashScreen - initState ${DateTime.now().toString()}');
_viewModel.checkUpdateResponse = (data) {
WidgetsBinding.instance.addPostFrameCallback((_) {
final updateData = (data?.updateRequest ?? []).firstOrNull;
......@@ -40,6 +42,31 @@ class _SplashScreenState extends BaseState<SplashScreen> with BasicState {
_viewModel.checkUpdateApp();
}
@override
void didChangeDependencies() {
super.didChangeDependencies();
if (kIsWeb && _webSplashCacheFuture == null) {
_webSplashCacheFuture = precacheImage(
const AssetImage('assets/images/splash_screen.webp'),
context,
).catchError((error, stackTrace) {
debugPrint('Failed to precache splash background: $error');
debugPrintStack(stackTrace: stackTrace);
}).whenComplete(() {
if (!mounted) return;
WidgetsBinding.instance.addPostFrameCallback((_) {
_notifyWebLoaderReady();
});
});
}
}
void _notifyWebLoaderReady() {
if (!kIsWeb || _webLoaderNotified || !mounted) return;
_webLoaderNotified = true;
webNotifySplashScreenReady();
}
@override
Widget createBody() {
final path = kIsWeb ? "assets/images/splash_screen.webp" : "assets/images/splash_screen.png";
......@@ -53,7 +80,9 @@ class _SplashScreenState extends BaseState<SplashScreen> with BasicState {
height: double.infinity,
fit: BoxFit.cover,
),
Center(child: CircularProgressIndicator()),
Center(
child: kIsWeb ? SizedBox.shrink() : CircularProgressIndicator()
)
],
),
);
......
import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:get/get.dart';
import 'package:mypoint_flutter_app/extensions/string_extension.dart';
import 'package:mypoint_flutter_app/networking/restful_api_viewmodel.dart';
import 'package:mypoint_flutter_app/networking/restful_api_client_all_request.dart';
import 'package:mypoint_flutter_app/core/utils/extensions/string_extension.dart';
import 'package:mypoint_flutter_app/core/network/restful_api_viewmodel.dart';
import 'package:mypoint_flutter_app/core/network/restful_api_client_all_request.dart';
import 'package:mypoint_flutter_app/shared/router_gage.dart';
import '../../model/auth/login_token_response_model.dart';
import '../../model/auth/profile_response_model.dart';
import '../login/model/login_token_response_model.dart';
import '../personal/model/profile_response_model.dart';
import 'models/update_response_model.dart';
import '../../preference/data_preference.dart';
import '../../preference/point/point_manager.dart';
import '../../shared/preferences/data_preference.dart';
import '../../shared/preferences/point/point_manager.dart';
import 'package:url_launcher/url_launcher.dart';
import '../../web/web_helper.dart';
import '../../core/services/web/web_helper.dart';
import '../popup_manager/popup_manager_viewmodel.dart';
class SplashScreenViewModel extends RestfulApiViewModel {
......
import 'package:json_annotation/json_annotation.dart';
// part 'support_item_model.g.dart';
enum SupportItemType { mail, phone, facebook, question, termsOfUse, privacyPolicy }
@JsonSerializable()
......
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:mypoint_flutter_app/screen/support/support_item_model.dart';
import 'package:mypoint_flutter_app/screen/support/support_screen_viewmodel.dart';
import 'package:mypoint_flutter_app/features/support/support_item_model.dart';
import 'package:mypoint_flutter_app/features/support/support_screen_viewmodel.dart';
import 'package:mypoint_flutter_app/shared/router_gage.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:universal_html/js_util.dart' as js_util;
import '../../widgets/custom_navigation_bar.dart';
import '../../shared/widgets/custom_navigation_bar.dart';
import '../faqs/faqs_screen.dart';
import '../pageDetail/model/detail_page_rule_type.dart';
import '../../web/web_helper.dart';
import '../../core/services/web/web_helper.dart';
class SupportScreen extends StatefulWidget {
const SupportScreen({super.key});
......@@ -123,8 +123,6 @@ class _SupportScreenState extends State<SupportScreen> {
return Icons.receipt_long;
case SupportItemType.privacyPolicy:
return Icons.lock_outline;
default:
return Icons.info;
}
}
......
......@@ -2,7 +2,7 @@ import 'dart:convert';
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
import 'package:get/get.dart';
import 'package:mypoint_flutter_app/screen/support/support_item_model.dart';
import 'package:mypoint_flutter_app/features/support/support_item_model.dart';
class SupportViewModel extends GetxController {
var supportItems = <SupportItemModel>[].obs;
......
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/models/product_brand_model.dart';
class BrandSelectSheet extends StatelessWidget {
......
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:intl/intl.dart';
import 'package:mypoint_flutter_app/extensions/string_extension.dart';
import 'package:mypoint_flutter_app/screen/topup/topup_viewmodel.dart';
import 'package:mypoint_flutter_app/widgets/custom_navigation_bar.dart';
import 'package:mypoint_flutter_app/widgets/image_loader.dart';
import '../../base/base_screen.dart';
import '../../base/basic_state.dart';
import '../../extensions/debouncer.dart';
import '../../preference/data_preference.dart';
import '../../resources/base_color.dart';
import 'package:mypoint_flutter_app/core/utils/extensions/string_extension.dart';
import 'package:mypoint_flutter_app/features/topup/topup_viewmodel.dart';
import 'package:mypoint_flutter_app/shared/widgets/custom_navigation_bar.dart';
import 'package:mypoint_flutter_app/shared/widgets/image_loader.dart';
import '../../shared/widgets/base_view/base_screen.dart';
import '../../shared/widgets/base_view/basic_state.dart';
import '../../core/utils/debouncer.dart';
import '../../shared/preferences/data_preference.dart';
import '../../core/theme/base_color.dart';
import '../../shared/router_gage.dart';
import '../contacts/contacts_picker.dart';
import 'brand_select_sheet_widget.dart';
......@@ -110,7 +110,7 @@ class _PhoneTopUpScreenState extends BaseState<PhoneTopUpScreen> with BasicState
selectedBrand: _viewModel.selectedBrand.value,
onSelected: (brand) {
Navigator.pop(context);
if (brand == null && brand.id != _viewModel.selectedBrand.value?.id) return;
if (brand.id != _viewModel.selectedBrand.value?.id) return;
_viewModel.selectedProduct.value = null;
_viewModel.selectedBrand.value = brand;
_viewModel.getTelcoDetail();
......@@ -154,7 +154,7 @@ class _PhoneTopUpScreenState extends BaseState<PhoneTopUpScreen> with BasicState
scrollDirection: Axis.horizontal,
padding: const EdgeInsets.symmetric(horizontal: 8),
itemCount: histories.length,
separatorBuilder: (_, __) => const SizedBox(width: 8),
separatorBuilder: (_, _) => const SizedBox(width: 8),
itemBuilder: (_, index) {
final phone = histories[index];
final myPhone = DataPreference.instance.phone ?? '';
......
import 'package:get/get.dart';
import 'package:get/get_rx/src/rx_types/rx_types.dart';
import 'package:mypoint_flutter_app/networking/api/product_api.dart' deferred as product_api;
import 'package:mypoint_flutter_app/preference/data_preference.dart';
import 'package:mypoint_flutter_app/screen/topup/models/brand_network_model.dart';
import '../../base/base_response_model.dart';
import '../../networking/restful_api_viewmodel.dart';
import '../../preference/contact_storage_service.dart';
import 'package:mypoint_flutter_app/core/network/api/product_api.dart' deferred as product_api;
import 'package:mypoint_flutter_app/shared/preferences/data_preference.dart';
import 'package:mypoint_flutter_app/features/topup/models/brand_network_model.dart';
import '../../shared/widgets/base_view/base_response_model.dart';
import '../../core/network/restful_api_viewmodel.dart';
import '../../core/services/contact_storage_service.dart';
import '../voucher/models/product_brand_model.dart';
import '../voucher/models/product_model.dart';
import '../voucher/models/product_type.dart';
......@@ -50,11 +50,11 @@ class TopUpViewModel extends RestfulApiViewModel {
}
}
firstLoadTopUpData() async {
Future<void> firstLoadTopUpData() async {
_getTopUpBrands();
}
_getTopUpBrands() async {
Future<void> _getTopUpBrands() async {
await callApi<List<ProductBrandModel>>(
request: () => _callProductApi((api) => api.getTopUpBrands(ProductType.topupMobile)),
onSuccess: (data, _) {
......@@ -65,11 +65,11 @@ class TopUpViewModel extends RestfulApiViewModel {
);
}
checkMobileNetwork() async {
Future<void> checkMobileNetwork() async {
await callApi<BrandNameCheckResponse>(
request: () => _callProductApi((api) => api.checkMobileNetwork(phoneNumber.value)),
onSuccess: (data, _) {
final brandCode = data?.brand ?? '';
final brandCode = data.brand ?? '';
var brand = topUpBrands.isNotEmpty
? topUpBrands.firstWhere(
(brand) => brand.code == brandCode,
......
import 'dart:io';
import 'package:file_saver/file_saver.dart';
import 'package:flutter/material.dart';
import 'package:share_plus/share_plus.dart';
import 'package:webview_flutter/webview_flutter.dart';
import 'package:path_provider/path_provider.dart';
import 'package:http/http.dart' as http;
import '../../base/app_loading.dart';
import '../../base/base_screen.dart';
import '../../base/basic_state.dart';
import '../../resources/base_color.dart';
import '../../widgets/custom_navigation_bar.dart';
import '../../shared/widgets/loading/app_loading.dart';
import '../../shared/widgets/base_view/base_screen.dart';
import '../../shared/widgets/base_view/basic_state.dart';
import '../../core/theme/base_color.dart';
import '../../shared/widgets/custom_navigation_bar.dart';
import 'dart:typed_data' as typed_data;
class TrafficServiceCertificateScreen extends BaseScreen {
......
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:mypoint_flutter_app/screen/traffic_service/traffic_service_certificate_screen.dart';
import 'package:mypoint_flutter_app/screen/traffic_service/traffic_service_model.dart';
import 'package:mypoint_flutter_app/screen/traffic_service/traffic_service_viewmodel.dart';
import 'package:mypoint_flutter_app/widgets/custom_empty_widget.dart';
import 'package:mypoint_flutter_app/features/traffic_service/traffic_service_certificate_screen.dart';
import 'package:mypoint_flutter_app/features/traffic_service/traffic_service_model.dart';
import 'package:mypoint_flutter_app/features/traffic_service/traffic_service_viewmodel.dart';
import 'package:mypoint_flutter_app/shared/widgets/custom_empty_widget.dart';
import 'package:url_launcher/url_launcher.dart';
import '../../resources/base_color.dart';
import '../../widgets/custom_navigation_bar.dart';
import '../../core/theme/base_color.dart';
import '../../shared/widgets/custom_navigation_bar.dart';
class TrafficServiceDetailScreen extends StatefulWidget {
const TrafficServiceDetailScreen({super.key});
......@@ -52,7 +52,7 @@ class _TrafficServiceDetailScreenState extends State<TrafficServiceDetailScreen>
body: Obx(() {
final model = _viewModel.trafficServiceDetail.value;
if (model == null) {
return const Center(child: EmptyWidget());
return Center(child: EmptyWidget(isLoading: _viewModel.isLoading.value));
}
return Column(
children: [
......
import 'package:mypoint_flutter_app/directional/directional_screen.dart';
import 'package:mypoint_flutter_app/extensions/datetime_extensions.dart';
import 'package:mypoint_flutter_app/extensions/string_extension.dart';
import 'package:mypoint_flutter_app/shared/navigation/directional_screen.dart';
import 'package:mypoint_flutter_app/core/utils/extensions/datetime_extensions.dart';
import 'package:mypoint_flutter_app/core/utils/extensions/string_extension.dart';
enum SortFilter { asc, desc }
......@@ -30,12 +30,12 @@ class HeaderFilterOrderModel {
String get eventNameTracking {
if (sort == null) {
return 'soskdt_${suffixChecking}';
return 'soskdt_$suffixChecking';
}
return 'soskdt_${suffixChecking}_${sort!.name}';
}
String get eventNameTrackingDvCar => 'dvcar_${suffixChecking}';
String get eventNameTrackingDvCar => 'dvcar_$suffixChecking';
}
class TrafficServiceResponseModel {
......
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:mypoint_flutter_app/extensions/datetime_extensions.dart';
import 'package:mypoint_flutter_app/extensions/string_extension.dart';
import 'package:mypoint_flutter_app/screen/traffic_service/traffic_service_detail_screen.dart';
import 'package:mypoint_flutter_app/screen/traffic_service/traffic_service_viewmodel.dart';
import 'package:mypoint_flutter_app/widgets/custom_empty_widget.dart';
import 'package:mypoint_flutter_app/widgets/image_loader.dart';
import '../../extensions/date_format.dart';
import '../../resources/base_color.dart';
import 'package:mypoint_flutter_app/core/utils/extensions/datetime_extensions.dart';
import 'package:mypoint_flutter_app/core/utils/extensions/string_extension.dart';
import 'package:mypoint_flutter_app/features/traffic_service/traffic_service_viewmodel.dart';
import 'package:mypoint_flutter_app/shared/widgets/custom_empty_widget.dart';
import 'package:mypoint_flutter_app/shared/widgets/image_loader.dart';
import '../../core/utils/extensions/date_format.dart';
import '../../core/theme/base_color.dart';
import '../../shared/router_gage.dart';
import '../../widgets/custom_navigation_bar.dart';
import '../../shared/widgets/custom_navigation_bar.dart';
class TrafficServiceScreen extends StatefulWidget {
const TrafficServiceScreen({super.key});
......@@ -72,7 +70,7 @@ class _TrafficServiceScreenState extends State<TrafficServiceScreen> {
child: Obx(() {
final products = _viewModel.trafficData.value?.products ?? [];
return products.isEmpty
? Center(child: EmptyWidget())
? Center(child: EmptyWidget(isLoading: _viewModel.isLoading.value))
: ListView.builder(
itemCount: products.length,
itemBuilder: (context, index) {
......
import 'package:get/get_rx/src/rx_types/rx_types.dart';
import 'package:mypoint_flutter_app/configs/constants.dart';
import 'package:mypoint_flutter_app/networking/api/product_api.dart' deferred as product_api;
import 'package:mypoint_flutter_app/networking/restful_api_client_all_request.dart';
import 'package:mypoint_flutter_app/screen/traffic_service/traffic_service_model.dart';
import '../../networking/restful_api_viewmodel.dart';
import '../../base/base_response_model.dart';
import 'package:mypoint_flutter_app/app/config/constants.dart';
import 'package:mypoint_flutter_app/core/network/api/product_api.dart' deferred as product_api;
import 'package:mypoint_flutter_app/core/network/restful_api_client_all_request.dart';
import 'package:mypoint_flutter_app/features/traffic_service/traffic_service_model.dart';
import '../../core/network/restful_api_viewmodel.dart';
import '../../shared/widgets/base_view/base_response_model.dart';
class TrafficServiceViewModel extends RestfulApiViewModel {
var trafficData = Rxn<TrafficServiceResponseModel>();
......
......@@ -2,11 +2,8 @@ class TransactionCategoryModel {
int? id;
String? code;
String? name;
bool _isSelected = false;
bool get isSelected => _isSelected;
set isSelected(bool value) => _isSelected = value;
TransactionCategoryModel({
this.id,
......
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