Commit b3c72190 authored by DatHV's avatar DatHV
Browse files

update invite friend.

update config build
parent 6b980613
...@@ -33,7 +33,7 @@ class _SplashScreenState extends BaseState<SplashScreen> with BasicState { ...@@ -33,7 +33,7 @@ class _SplashScreenState extends BaseState<SplashScreen> with BasicState {
return; return;
} }
if (updateData.status == UpdateStatus.none) { if (updateData.status == UpdateStatus.none) {
_viewModel.directionWhenTokenInvalid(); _viewModel.makeDataFollowInitApp();
} else { } else {
_showSuggestUpdateAlert(updateData); _showSuggestUpdateAlert(updateData);
} }
......
...@@ -106,7 +106,6 @@ class SplashScreenViewModel extends RestfulApiViewModel { ...@@ -106,7 +106,6 @@ class SplashScreenViewModel extends RestfulApiViewModel {
} }
Future<void> directionWhenTokenInvalid() async { Future<void> directionWhenTokenInvalid() async {
if (Get.currentRoute == onboardingScreen) return;
// if (kIsWeb) { // if (kIsWeb) {
// print('❌ No token found on web, closing app'); // print('❌ No token found on web, closing app');
// final closeSuccess = await webCloseApp({ // final closeSuccess = await webCloseApp({
......
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import '../../app/routing/directional_action_type.dart'; import '../../app/routing/directional_action_type.dart';
...@@ -32,14 +33,23 @@ class _VoucherTabScreenState extends State<VoucherTabScreen> with PopupOnInit { ...@@ -32,14 +33,23 @@ class _VoucherTabScreenState extends State<VoucherTabScreen> with PopupOnInit {
return Scaffold( return Scaffold(
appBar: CustomNavigationBar( appBar: CustomNavigationBar(
title: "Ưu đãi", title: "Ưu đãi",
leftButtons: [], leftButtons: [
if (kIsWeb)
IconButton(
icon: const Icon(Icons.search, color: Colors.white),
onPressed: () {
Get.toNamed(vouchersScreen, arguments: {"enableSearch": true});
},
),
],
rightButtons: [ rightButtons: [
IconButton( if (!kIsWeb)
icon: const Icon(Icons.search, color: Colors.white), IconButton(
onPressed: () { icon: const Icon(Icons.search, color: Colors.white),
Get.toNamed(vouchersScreen, arguments: {"enableSearch": true}); onPressed: () {
}, Get.toNamed(vouchersScreen, arguments: {"enableSearch": true});
), },
),
], ],
), ),
body: Obx(() { body: Obx(() {
......
...@@ -372,7 +372,7 @@ class DirectionalScreen { ...@@ -372,7 +372,7 @@ class DirectionalScreen {
} }
} }
void _logUnsupported(type) { void _logUnsupported(DirectionalScreenName type) {
debugPrint("⚠️ DirectionalScreen action type không được hỗ trợ: ${type.rawValue}"); debugPrint("⚠️ DirectionalScreen action type không được hỗ trợ: ${type.rawValue}");
} }
......
...@@ -68,6 +68,8 @@ const qrCodeScreen = '/qrCodeScreen'; ...@@ -68,6 +68,8 @@ const qrCodeScreen = '/qrCodeScreen';
const myMobileCardDetailScreen = '/myMobileCardDetailScreen'; const myMobileCardDetailScreen = '/myMobileCardDetailScreen';
const healthBookCardDetail = '/healthBookCardDetail'; const healthBookCardDetail = '/healthBookCardDetail';
const notificationDetailScreen = '/notificationDetailScreen'; const notificationDetailScreen = '/notificationDetailScreen';
const referralCodeInviteFriendScreen = '/referralCodeInviteFriendScreen';
const campaignInviteReferralInfoScreen = '/campaignInviteReferralInfoScreen';
class RouterPage { class RouterPage {
static List<GetPage> pages() { static List<GetPage> pages() {
...@@ -138,6 +140,8 @@ class RouterPage { ...@@ -138,6 +140,8 @@ class RouterPage {
GetPage(name: healthBookScreen, page: () => const HealthBookDeferredScreen()), GetPage(name: healthBookScreen, page: () => const HealthBookDeferredScreen()),
GetPage(name: healthBookCardDetail, page: () => const HealthBookCardDetailDeferredScreen()), GetPage(name: healthBookCardDetail, page: () => const HealthBookCardDetailDeferredScreen()),
GetPage(name: notificationDetailScreen, page: () => NotificationDetailScreen()), GetPage(name: notificationDetailScreen, page: () => NotificationDetailScreen()),
GetPage(name: referralCodeInviteFriendScreen, page: () => const ReferralCodeInviteFriendDeferredScreen()),
GetPage(name: campaignInviteReferralInfoScreen, page: () => const CampaignInviteReferralInfoDeferredScreen()),
]; ];
} }
} }
\ No newline at end of file
import 'package:flutter/material.dart';
class ButtonContainer extends StatelessWidget {
final Color color;
final double cornerRadius;
final double? height;
final double? width;
final Widget child;
final bool visible;
const ButtonContainer({
super.key,
required this.child,
this.height,
this.width,
this.color = Colors.white,
this.cornerRadius = 8,
this.visible = true,
});
@override
Widget build(BuildContext context) {
return Visibility(
visible: visible,
child: Container(
decoration: BoxDecoration(borderRadius: BorderRadius.circular(cornerRadius), color: color),
width: width,
height: height,
child: child,
),
);
}
}
import 'package:flutter/material.dart';
import 'back_button.dart';
class CustomAppBar extends StatelessWidget implements PreferredSizeWidget {
final String title;
final List<Widget> leftButtons;
final List<Widget> rightButtons;
final double height;
const CustomAppBar({
super.key,
required this.title,
this.leftButtons = const [],
this.rightButtons = const [],
this.height = 56,
});
static CustomAppBar back({required String title}) {
return CustomAppBar(title: title, leftButtons: [CustomBackButton()]);
}
@override
Widget build(BuildContext context) {
return SafeArea(
child: Container(
height: height,
padding: const EdgeInsets.symmetric(horizontal: 16),
child: Stack(
alignment: Alignment.center,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [Row(children: leftButtons), Row(children: rightButtons)],
),
Padding(
padding: const EdgeInsets.only(left: 24, right: 24),
child: Center(
child: Text(
title,
textAlign: TextAlign.center,
maxLines: 1,
style: const TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: Colors.black87,
),
),
),
),
],
),
),
);
}
@override
Size get preferredSize => Size.fromHeight(height);
}
\ No newline at end of file
import 'package:auto_size_text/auto_size_text.dart'; import 'package:auto_size_text/auto_size_text.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import '../../app/config/constants.dart';
import '../../features/home/header_home_viewmodel.dart'; import '../../features/home/header_home_viewmodel.dart';
import 'back_button.dart'; import 'back_button.dart';
import 'image_loader.dart'; import 'image_loader.dart';
...@@ -21,7 +23,15 @@ class CustomNavigationBar extends StatelessWidget implements PreferredSizeWidget ...@@ -21,7 +23,15 @@ class CustomNavigationBar extends StatelessWidget implements PreferredSizeWidget
}); });
@override @override
Size get preferredSize => const Size.fromHeight(kToolbarHeight); Size get preferredSize {
final dispatcher = WidgetsBinding.instance.platformDispatcher;
final view = dispatcher.implicitView ?? (dispatcher.views.isNotEmpty ? dispatcher.views.first : null);
double paddingTop = view != null ? MediaQueryData.fromView(view).padding.top : 0.0;
if (paddingTop == 0 && kIsWeb) {
paddingTop = Constants.webTopPadding;
}
return Size.fromHeight(kToolbarHeight + paddingTop);
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
...@@ -37,27 +47,28 @@ class CustomNavigationBar extends StatelessWidget implements PreferredSizeWidget ...@@ -37,27 +47,28 @@ class CustomNavigationBar extends StatelessWidget implements PreferredSizeWidget
} }
Widget _buildAppBar(String bgImage, BuildContext context) { Widget _buildAppBar(String bgImage, BuildContext context) {
final double statusBarHeight = MediaQuery.of(context).padding.top; double statusBarHeight = MediaQuery.of(context).padding.top;
double extraWebPadding = 0;
if (statusBarHeight == 0 && kIsWeb) {
extraWebPadding = Constants.webTopPadding;
}
final double totalTopPadding = statusBarHeight + extraWebPadding;
final bool isHttp = bgImage.startsWith('http://') || bgImage.startsWith('https://'); final bool isHttp = bgImage.startsWith('http://') || bgImage.startsWith('https://');
final paddingTitle = (leftButtons.isNotEmpty || rightButtons.isNotEmpty) ? 48.0 : 16.0; // cách 2 đầu final paddingTitle = (leftButtons.isNotEmpty || rightButtons.isNotEmpty) ? 48.0 : 16.0; // cách 2 đầu
return Container( return Container(
height: statusBarHeight + kToolbarHeight, height: totalTopPadding + kToolbarHeight,
decoration: BoxDecoration( decoration: BoxDecoration(color: bgImage.isEmpty ? Colors.white : null),
color: bgImage.isEmpty ? Colors.white : null, child: Stack(
), fit: StackFit.expand,
child: Stack( children: [
fit: StackFit.expand, if (bgImage.isNotEmpty)
children: [ isHttp
if (bgImage.isNotEmpty) ? loadNetworkImage(url: bgImage, fit: BoxFit.cover, placeholderAsset: _defaultBgImage)
isHttp : Image.asset(_defaultBgImage, fit: BoxFit.cover),
? loadNetworkImage( SafeArea(
url: bgImage, bottom: false,
fit: BoxFit.cover, child: Padding(
placeholderAsset: _defaultBgImage, padding: EdgeInsets.only(top: extraWebPadding),
)
: Image.asset(_defaultBgImage, fit: BoxFit.cover),
SafeArea(
bottom: false,
child: Stack( child: Stack(
alignment: Alignment.center, alignment: Alignment.center,
children: [ children: [
...@@ -66,49 +77,28 @@ class CustomNavigationBar extends StatelessWidget implements PreferredSizeWidget ...@@ -66,49 +77,28 @@ class CustomNavigationBar extends StatelessWidget implements PreferredSizeWidget
child: AutoSizeText( child: AutoSizeText(
title, title,
maxLines: 1, maxLines: 1,
minFontSize: 12, // 👈 không nhỏ hơn 8 minFontSize: 12,
stepGranularity: 0.1, // scale mượt hơn stepGranularity: 0.1,
overflow: TextOverflow.visible, // giữ nguyên như bạn đang dùng overflow: TextOverflow.visible,
// giữ nguyên như bạn đang dùng
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: const TextStyle( style: const TextStyle(
fontSize: 18, // 👈 cỡ tối đa mong muốn fontSize: 18, // 👈 cỡ tối đa mong muốn
fontWeight: FontWeight.w800, fontWeight: FontWeight.w800,
color: Colors.white, color: Colors.white,
), ),
), ),
// child: FittedBox(
// fit: BoxFit.scaleDown, // tự giảm font để vừa khung
// child: Text(
// title,
// maxLines: 1,
// softWrap: false,
// overflow: TextOverflow.visible, // không dùng ellipsis
// textAlign: TextAlign.center,
// style: const TextStyle(
// fontSize: 18, // cỡ tối đa
// fontWeight: FontWeight.w800,
// color: Colors.white,
// ),
// ),
// ),
), ),
// Text(
// title,
// maxLines: 1,
// style: const TextStyle(fontSize: 18, fontWeight: FontWeight.w800, color: Colors.white),
// textAlign: TextAlign.center,
// ),
// Buttons bên trái
if (leftButtons.isNotEmpty) if (leftButtons.isNotEmpty)
Positioned(left: 12, child: Row(mainAxisSize: MainAxisSize.min, children: leftButtons)), Positioned(left: 12, child: Row(mainAxisSize: MainAxisSize.min, children: leftButtons)),
// Buttons bên phải
if (rightButtons.isNotEmpty) if (rightButtons.isNotEmpty)
Positioned(right: 12, child: Row(mainAxisSize: MainAxisSize.min, children: rightButtons)), Positioned(right: 12, child: Row(mainAxisSize: MainAxisSize.min, children: rightButtons)),
], ],
), ),
), ),
], ),
), ],
); ),
);
} }
} }
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import '../../app/config/constants.dart';
import '../../features/home/header_home_viewmodel.dart'; import '../../features/home/header_home_viewmodel.dart';
import 'back_button.dart'; import 'back_button.dart';
import 'image_loader.dart'; import 'image_loader.dart';
...@@ -21,7 +23,15 @@ class CustomSearchNavigationBar extends StatefulWidget implements PreferredSizeW ...@@ -21,7 +23,15 @@ class CustomSearchNavigationBar extends StatefulWidget implements PreferredSizeW
}); });
@override @override
Size get preferredSize => const Size.fromHeight(kToolbarHeight); Size get preferredSize {
final dispatcher = WidgetsBinding.instance.platformDispatcher;
final view = dispatcher.implicitView ?? (dispatcher.views.isNotEmpty ? dispatcher.views.first : null);
double paddingTop = view != null ? MediaQueryData.fromView(view).padding.top : 0.0;
if (paddingTop == 0 && kIsWeb) {
paddingTop = Constants.webTopPadding;
}
return Size.fromHeight(kToolbarHeight + paddingTop);
}
@override @override
_CustomSearchNavigationBarState createState() => _CustomSearchNavigationBarState(); _CustomSearchNavigationBarState createState() => _CustomSearchNavigationBarState();
...@@ -51,16 +61,14 @@ class _CustomSearchNavigationBarState extends State<CustomSearchNavigationBar> { ...@@ -51,16 +61,14 @@ class _CustomSearchNavigationBarState extends State<CustomSearchNavigationBar> {
Widget _buildAppBar(String bgImage, BuildContext context) { Widget _buildAppBar(String bgImage, BuildContext context) {
final bool isHttp = bgImage.startsWith('http://') || bgImage.startsWith('https://'); final bool isHttp = bgImage.startsWith('http://') || bgImage.startsWith('https://');
final double statusBarHeight = MediaQuery.of(context).padding.top; double statusBarHeight = MediaQuery.of(context).padding.top;
double extraWebPadding = 0;
if (statusBarHeight == 0 && kIsWeb) {
extraWebPadding = Constants.webTopPadding;
}
final double totalTopPadding = statusBarHeight + extraWebPadding;
return SizedBox( return SizedBox(
height: statusBarHeight + kToolbarHeight, height: totalTopPadding + kToolbarHeight,
// decoration: BoxDecoration(
// image:
// widget.backgroundImage != null
// ? DecorationImage(image: AssetImage(widget.backgroundImage!), fit: BoxFit.cover)
// : null,
// color: widget.backgroundImage == null ? Colors.white : null,
// ),
child: Stack( child: Stack(
fit: StackFit.expand, fit: StackFit.expand,
children: [ children: [
...@@ -70,52 +78,55 @@ class _CustomSearchNavigationBarState extends State<CustomSearchNavigationBar> { ...@@ -70,52 +78,55 @@ class _CustomSearchNavigationBarState extends State<CustomSearchNavigationBar> {
: Image.asset(_defaultBgImage, fit: BoxFit.cover), : Image.asset(_defaultBgImage, fit: BoxFit.cover),
SafeArea( SafeArea(
bottom: false, bottom: false,
child: Stack( child: Padding(
alignment: Alignment.center, padding: EdgeInsets.only(top: extraWebPadding),
children: [ child: Stack(
Positioned( alignment: Alignment.center,
left: widget.showBackButton ? 68 : 16, children: [
right: widget.rightButtons.isNotEmpty ? 60 : 16, Positioned(
child: Container( left: widget.showBackButton ? 68 : 16,
height: 36, right: widget.rightButtons.isNotEmpty ? 60 : 16,
padding: const EdgeInsets.symmetric(horizontal: 8), child: Container(
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(12)), height: 36,
child: Row( padding: const EdgeInsets.symmetric(horizontal: 8),
children: [ decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(12)),
const Icon(Icons.search, size: 20), child: Row(
const SizedBox(width: 4), children: [
Expanded( const Icon(Icons.search, size: 20),
child: TextField( const SizedBox(width: 4),
controller: _controller, Expanded(
onChanged: (value) { child: TextField(
setState(() {}); // Update UI for suffix icon controller: _controller,
widget.onSearchChanged?.call(value); onChanged: (value) {
}, setState(() {}); // Update UI for suffix icon
decoration: InputDecoration( widget.onSearchChanged?.call(value);
border: InputBorder.none, },
hintText: widget.hintText, decoration: InputDecoration(
isDense: true, border: InputBorder.none,
contentPadding: EdgeInsets.zero, hintText: widget.hintText,
isDense: true,
contentPadding: EdgeInsets.zero,
),
), ),
), ),
), if (_controller.text.isNotEmpty)
if (_controller.text.isNotEmpty) GestureDetector(
GestureDetector( onTap: () {
onTap: () { _controller.clear();
_controller.clear(); widget.onSearchChanged?.call('');
widget.onSearchChanged?.call(''); setState(() {});
setState(() {}); },
}, child: const Icon(Icons.close, size: 20),
child: const Icon(Icons.close, size: 20), ),
), ],
], ),
), ),
), ),
), if (widget.showBackButton) Positioned(left: 12, child: CustomBackButton()),
if (widget.showBackButton) Positioned(left: 12, child: CustomBackButton()), if (widget.rightButtons.isNotEmpty)
if (widget.rightButtons.isNotEmpty) Positioned(right: 12, child: Row(mainAxisSize: MainAxisSize.min, children: widget.rightButtons)),
Positioned(right: 12, child: Row(mainAxisSize: MainAxisSize.min, children: widget.rightButtons)), ],
], ),
), ),
), ),
], ],
......
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