diff --git a/lib/extensions/context_extension.dart b/lib/extensions/context_extension.dart index 89e89ab0..350460db 100644 --- a/lib/extensions/context_extension.dart +++ b/lib/extensions/context_extension.dart @@ -1,10 +1,15 @@ import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; import 'package:localization/localization.dart'; +import 'package:provider/provider.dart'; +import '../controllers/providers/settings/setting_provider.dart'; import '../models/enums/translation_keys.dart'; extension BuildContextExtension on BuildContext { String translate(TranslationKeys translationKey) { return translationKey.name.i18n([Localizations.localeOf(this).toString()]); } + + bool get isDark => Provider.of(this).theme.brightness == Brightness.dark; } diff --git a/lib/main.dart b/lib/main.dart index 7435cbc6..3f58ad98 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -6,6 +6,7 @@ import 'package:flutter_localizations/flutter_localizations.dart'; import 'package:localization/localization.dart'; import 'package:provider/provider.dart'; import 'package:test_sa/new_views/app_style/app_themes.dart'; +import 'package:test_sa/new_views/pages/land_page/land_page.dart'; import 'package:test_sa/new_views/pages/login_page.dart'; import 'package:test_sa/new_views/pages/splash_page.dart'; @@ -64,6 +65,7 @@ class MyApp extends StatelessWidget { routes: { SplashPage.routeName: (_) => const SplashPage(), LoginPage.routeName: (_) => const LoginPage(), + LandPage.routeName: (_) => const LandPage(), }, ), ), diff --git a/lib/new_views/app_style/app_color.dart b/lib/new_views/app_style/app_color.dart index 47b5c6eb..995c907a 100644 --- a/lib/new_views/app_style/app_color.dart +++ b/lib/new_views/app_style/app_color.dart @@ -10,6 +10,7 @@ class AppColor { static const Color primary70 = Color(0xff163A51); //texts + static const Color neutral10 = Color(0xffBCBCBC); static const Color neutral20 = Color(0xff767676); static const Color neutral30 = Color(0xffEAF1F4); static const Color neutral40 = Color(0xffE4E5E6); @@ -19,7 +20,7 @@ class AppColor { //background static const Color backgroundLight = Color(0xffF7F9FB); - static const Color backgroundDark = neutral50; + static const Color backgroundDark = Color(0xff111427); //red static const Color red40 = Color(0xffFFDBDC); diff --git a/lib/new_views/app_style/app_themes.dart b/lib/new_views/app_style/app_themes.dart index 06488882..7aaf50cb 100644 --- a/lib/new_views/app_style/app_themes.dart +++ b/lib/new_views/app_style/app_themes.dart @@ -3,20 +3,18 @@ import 'package:test_sa/new_views/app_style/app_color.dart'; class AppThemes { AppThemes._(); - static final ThemeData _data = ThemeData( - fontFamily: "Poppins", + static ThemeData lightTheme = ThemeData.light().copyWith( + textTheme: ThemeData.light().textTheme.apply(fontFamily: "Poppins"), primaryColor: AppColor.primary50, indicatorColor: AppColor.primary50, - ); - - static ThemeData lightTheme = _data.copyWith( - brightness: Brightness.light, scaffoldBackgroundColor: AppColor.backgroundLight, colorScheme: const ColorScheme.light(primary: AppColor.primary50, onPrimary: Colors.white, secondary: Colors.white, onSecondary: AppColor.neutral70), ); - static ThemeData darkTheme = _data.copyWith( - brightness: Brightness.dark, + static ThemeData darkTheme = ThemeData.dark().copyWith( + textTheme: ThemeData.light().textTheme.apply(fontFamily: "Poppins"), + primaryColor: AppColor.primary50, + indicatorColor: AppColor.primary50, scaffoldBackgroundColor: AppColor.backgroundDark, colorScheme: const ColorScheme.light(primary: AppColor.primary50, onPrimary: AppColor.neutral60, secondary: AppColor.neutral60, onSecondary: Colors.white), ); diff --git a/lib/new_views/common_widgets/app_drawer.dart b/lib/new_views/common_widgets/app_drawer.dart new file mode 100644 index 00000000..b5954633 --- /dev/null +++ b/lib/new_views/common_widgets/app_drawer.dart @@ -0,0 +1,48 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:test_sa/extensions/context_extension.dart'; + +import '../../controllers/providers/api/user_provider.dart'; +import '../../controllers/providers/settings/setting_provider.dart'; +import '../../models/enums/translation_keys.dart'; +import '../app_style/app_themes.dart'; +import 'app_filled_button.dart'; + +class AppDrawer extends StatelessWidget { + const AppDrawer({Key key}) : super(key: key); + + @override + Widget build(BuildContext context) { + final settingProvider = Provider.of(context, listen: false); + final userProvider = Provider.of(context, listen: false); + return Drawer( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + AppFilledButton( + label: TranslationKeys.login, + onPressed: () async { + // bool result = await showDialog( + // context: context, + // builder: (_) => const AAlertDialog( + // title: "_subtitle.signOut", + // content: "_subtitle.signOutAlert", + // ), + // ); + if (true) { + settingProvider.resetSettings(); + userProvider.reset(); + Navigator.of(context).pop(); + } + }), + Switch.adaptive( + value: context.isDark, + onChanged: (dark) { + Provider.of(context, listen: false).setTheme(dark ? AppThemes.darkTheme : AppThemes.lightTheme); + }, + ), + ], + ), + ); + } +} diff --git a/lib/new_views/common_widgets/app_text_form_field.dart b/lib/new_views/common_widgets/app_text_form_field.dart index 450b47e9..4b0f4a2e 100644 --- a/lib/new_views/common_widgets/app_text_form_field.dart +++ b/lib/new_views/common_widgets/app_text_form_field.dart @@ -68,7 +68,7 @@ class _AppTextFormFieldState extends State { Container( height: widget.textInputType == TextInputType.multiline ? null : 56.toScreenHeight, decoration: BoxDecoration( - color: Colors.white, + color: context.isDark ? AppColor.neutral50 : Colors.white, borderRadius: BorderRadius.circular(10), boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.05), blurRadius: 10)], ), @@ -99,8 +99,8 @@ class _AppTextFormFieldState extends State { enabledBorder: InputBorder.none, contentPadding: EdgeInsets.zero, constraints: const BoxConstraints(), - errorStyle: Theme.of(context).textTheme.bodySmall?.copyWith(color: AppColor.red60, height: 0.7), - floatingLabelStyle: Theme.of(context).textTheme.labelLarge?.copyWith(color: AppColor.neutral20, fontWeight: FontWeight.w500), + errorStyle: Theme.of(context).textTheme.bodySmall?.copyWith(color: context.isDark ? AppColor.red50 : AppColor.red60, height: 0.7), + floatingLabelStyle: Theme.of(context).textTheme.labelLarge?.copyWith(color: context.isDark ? null : AppColor.neutral20, fontWeight: FontWeight.w500), hintText: widget.hintText != null ? context.translate(widget.hintText) : null, labelText: widget.labelText != null ? context.translate(widget.labelText) : null, suffixIcon: widget.prefixIconData == null diff --git a/lib/new_views/pages/land_page/dashboard_page_indicator.dart b/lib/new_views/pages/land_page/dashboard_page_indicator.dart new file mode 100644 index 00000000..ef430b7d --- /dev/null +++ b/lib/new_views/pages/land_page/dashboard_page_indicator.dart @@ -0,0 +1,30 @@ +import 'package:flutter/material.dart'; +import 'package:test_sa/extensions/int_extensions.dart'; + +import '../../app_style/app_color.dart'; + +class DashboardPageIndicator extends StatelessWidget { + final PageController controller; + final int index, currentPage; + const DashboardPageIndicator({ + Key key, + @required this.controller, + @required this.index, + @required this.currentPage, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + final bool isActive = currentPage == (index + 1); + return InkWell( + onTap: () { + controller.animateToPage(index, duration: const Duration(milliseconds: 500), curve: Curves.ease); + }, + child: Container( + width: (isActive ? 30 : 16).toScreenWidth, + height: 9.toScreenHeight, + decoration: BoxDecoration(color: isActive ? AppColor.green50 : AppColor.neutral40, borderRadius: BorderRadius.circular(8)), + ), + ); + } +} diff --git a/lib/new_views/pages/land_page/land_page.dart b/lib/new_views/pages/land_page/land_page.dart new file mode 100644 index 00000000..072180cd --- /dev/null +++ b/lib/new_views/pages/land_page/land_page.dart @@ -0,0 +1,112 @@ +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:test_sa/extensions/context_extension.dart'; +import 'package:test_sa/extensions/int_extensions.dart'; +import 'package:test_sa/new_views/app_style/app_color.dart'; + +import '../../common_widgets/app_drawer.dart'; +import 'dashboard_page_indicator.dart'; + +class LandPage extends StatefulWidget { + static const String routeName = "/land-page"; + const LandPage({Key key}) : super(key: key); + + @override + State createState() => _LandPageState(); +} + +class _LandPageState extends State { + PageController _controller; + int _currentPage = 1; + + @override + void initState() { + super.initState(); + _controller = PageController() + ..addListener(() { + _currentPage = _controller.page.toInt() + 1; + setState(() {}); + }); + } + + @override + void dispose() { + _controller.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return WillPopScope( + onWillPop: () async { + // bool result = await showDialog( + // context: context, + // builder: (_) => const AAlertDialog( + // title: "_subtitle.exit", + // content: "_subtitle.exitAlert", + // ), + // ); + if (true) { + if (Platform.isAndroid) { + SystemChannels.platform.invokeMethod('SystemNavigator.pop'); + } else { + exit(0); + } + } + return false; + }, + child: Scaffold( + appBar: AppBar(), + body: Padding( + padding: EdgeInsets.only(left: 16.toScreenWidth, top: 11.toScreenHeight), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + DashboardPageIndicator(index: 0, currentPage: _currentPage, controller: _controller), + 3.width, + DashboardPageIndicator(index: 1, currentPage: _currentPage, controller: _controller), + 3.width, + DashboardPageIndicator(index: 2, currentPage: _currentPage, controller: _controller), + 10.width, + Text( + "0$_currentPage/03", + style: Theme.of(context).textTheme.labelMedium?.copyWith(fontWeight: FontWeight.w500, color: context.isDark ? AppColor.neutral40 : AppColor.neutral60), + ), + ], + ), + 8.height, + Expanded( + child: PageView( + controller: _controller, + children: const [ + Center( + child: Text('First Page'), + ), + Center( + child: Text('Second Page'), + ), + Center( + child: Text('Third Page'), + ), + ], + ), + ), + ], + ), + ), + bottomNavigationBar: BottomNavigationBar( + items: [ + BottomNavigationBarItem(icon: Icon(Icons.add), label: "add"), + BottomNavigationBarItem(icon: Icon(Icons.add), label: "add"), + BottomNavigationBarItem(icon: Icon(Icons.add), label: "add"), + ], + ), + drawer: const AppDrawer(), + ), + ); + } +} diff --git a/lib/new_views/pages/login_page.dart b/lib/new_views/pages/login_page.dart index db37d93e..133d296e 100644 --- a/lib/new_views/pages/login_page.dart +++ b/lib/new_views/pages/login_page.dart @@ -7,6 +7,7 @@ import 'package:test_sa/extensions/int_extensions.dart'; import 'package:test_sa/models/enums/translation_keys.dart'; import 'package:test_sa/new_views/app_style/app_color.dart'; import 'package:test_sa/new_views/common_widgets/app_lazy_loading.dart'; +import 'package:test_sa/new_views/pages/land_page/land_page.dart'; import '../../controllers/providers/api/user_provider.dart'; import '../../controllers/providers/settings/setting_provider.dart'; @@ -57,11 +58,11 @@ class _LoginPageState extends State { 64.height, Text( context.translate(TranslationKeys.login), - style: Theme.of(context).textTheme.headlineSmall?.copyWith(color: AppColor.neutral50, fontWeight: FontWeight.w600), + style: Theme.of(context).textTheme.headlineSmall?.copyWith(color: context.isDark ? AppColor.primary50 : AppColor.neutral50, fontWeight: FontWeight.w600), ), Text( context.translate(TranslationKeys.enterCredsToLogin), - style: Theme.of(context).textTheme.titleMedium?.copyWith(color: AppColor.neutral20, fontWeight: FontWeight.w500), + style: Theme.of(context).textTheme.titleMedium?.copyWith(color: context.isDark ? AppColor.neutral10 : AppColor.neutral20, fontWeight: FontWeight.w500), ), 32.height, AppTextFormField( @@ -122,8 +123,7 @@ class _LoginPageState extends State { Navigator.pop(context); if (status >= 200 && status < 300 && _userProvider.user.isAuthenticated ?? false) { _settingProvider.setUser(_userProvider.user); - - /// TODO [zaid] : push to home page + Navigator.pushNamed(context, LandPage.routeName); } else { Fluttertoast.showToast(msg: _userProvider.user.message); } diff --git a/lib/new_views/pages/splash_page.dart b/lib/new_views/pages/splash_page.dart index 1ca03e96..139eb2fd 100644 --- a/lib/new_views/pages/splash_page.dart +++ b/lib/new_views/pages/splash_page.dart @@ -11,6 +11,7 @@ import 'package:test_sa/models/app_notification.dart'; import 'package:test_sa/new_views/pages/login_page.dart'; import '../../models/size_config.dart'; +import 'land_page/land_page.dart'; class SplashPage extends StatefulWidget { static const String routeName = '/splash_page'; @@ -49,10 +50,10 @@ class _SplashPageState extends State { fit: BoxFit.contain, animation: "splash", callback: (animation) async { - Navigator.of(context).pushNamed(LoginPage.routeName); + Navigator.of(context).pushNamedAndRemoveUntil(LoginPage.routeName, (routes) => true); if (_settingProvider.isLoaded && (_settingProvider.user?.isLiveToken ?? false)) { _userProvider.user = _settingProvider.user; - // TODO [zaid] : push to home page + Navigator.of(context).pushNamedAndRemoveUntil(LandPage.routeName, (routes) => true); } }, ), diff --git a/lib/views/pages/user/land_page.dart b/lib/views/pages/user/land_page.dart index e249206d..03d46aa6 100644 --- a/lib/views/pages/user/land_page.dart +++ b/lib/views/pages/user/land_page.dart @@ -37,6 +37,7 @@ import 'package:url_launcher/url_launcher.dart'; import '../../widgets/land_page/land_page_item.dart'; import 'requests/requests_page.dart'; +@Deprecated("Use the widget inside the [new_views/pages/land_page] folder") class LandPage extends StatefulWidget { static const String id = "/land-page";